Embedded Stimulsoft Designer Control and MVVM
<wpfdesign:StiWpfDesignerControl></wpfdesign:StiWpfDesignerControl>
Don’t miss out adding the namespace
xmlns:wpfdesign="clr-namespace:Stimulsoft.Report.WpfDesign;assembly=Stimulsoft.Report.WpfDesign"
For sake of example, we would mock our business object rather than taking it out of Database
public class Products { public string Name { get; set; } public decimal Price { get; set; } } var _ProductCollection = new List() { new ProductModel() { Name = "Product 1", Price = 100 }, new ProductModel() { Name = "Product 2", Price = 200 } };
We do have a property ‘ActiveReport’ , which holds the report details and is responsible for synchronizing the dictionary. Let’s define the Property and synchronize our collection.
private Stimulsoft.Report.StiReport _ActiveReport; public Stimulsoft.Report.StiReport ActiveReport { get { return _ActiveReport; } set { _ActiveReport = value; this.NotifyOfPropertyChange(nameof(ActiveReport)); } }
And the code to register the collection with StiReport.
ActiveReport = new Stimulsoft.Report.StiReport(); ActiveReport.RegBusinessObject("Products", _ProductCollection); ActiveReport.Dictionary.Synchronize();
This is where our problems begin. We do not have a property (the Report Property doesn’t allow Binding) exposed by Stimulsoft Designer to which could bind the StiReport Instance. We can do it pragmatically by assigning the Report Property, but that would involve breaking the MVVM Structure. We would prefer not to do that, atleast not directly. So what would be our workaround ?
Supervising Controller Pattern
The workaround lies with having a Supervising Controlling Pattern. The Supervising Controller allows the ViewModel to be aware of the View, but not depended on it. Now this can be a tricky situation if someone questions whether this would be breaking the MVVM, considering as per MVVM, the ViewModel should be completely independent of View. Pretty much true, but when all doors are closed, there is nothing wrong in making the ViewModel ‘aware‘ of View, as long as it is not dependent on View and we do minimalist code in View. Remember, there is a significant difference in being aware and being dependent.
So how do we implement the Supervising Controlling Pattern and make the ViewModel aware of the View. We first being by creating the Contract interface through which the ViewModel would be interacting with View. Let’s call it ISupervisorController
public interface ISupervisingController { void UpdateReportControl(Stimulsoft.Report.StiReport Report); }
As you can see, it has a single method called UpdateReportControl, accepting the StiReport instance. Let’s go ahead and implement it in the View. We will make that only minimalist work is done in the code behind class.
public void UpdateReportControl(StiReport Report) { ReportDesigner.Report = Report; }
So with that done, we come to the most important part – how do we get an instance of View in the ViewModel ? Thanks to Caliburn.Micro, we do have a solution for that as well.
Screen and IViewAware
The Screen class in Caliburn.Micro utilizes an interface ‘IViewAware, which exposes a method called OnViewAttached which gives us reference to the attached View. All that left to do is override the method and use our Supervising Controller interface to call the method from View, which sets the Report property of Designer Control
protected override void OnViewAttached(object view, object context) { base.OnViewAttached(view, context); (view as ISupervisingController).UpdateReportControl(ActiveReport); }
That’s it, you have your .Net Object Collection synchronized with the Designer. The entire source code described in this post can be found here
One thought on “Stimulsoft – Non-Modal Designer in WPF App”