Methods to use constructor injection in user controls? - winforms

Are there any ways to enforce or allow constructor required dependencies for a user control without breaking the designer? What work arounds exist?
a default constructor with EditorBrowsable.Never
or property injection, but I prefer constructor injection.
other work-arounds or solutions?

Design user controls so that they don't use dependencies.
Look at the controls (ASP.NET, Windows Forms, WPF, etc.) supplied by Microsoft. None of them use dependencies. Instead, you assign data to them - often by way of writable properties.
This is a more SOLID design because a control's single responsibility should be to render data. Thus, if you also give it the responsibility of retrieving or formatting data, you are breaking the Single Responsibility Principle.
When you design controls like that, a default constructor becomes natural.

You can overload constructors. The designer is going to require the default constructor at design time so be sure to supply that one as well.
public UserControl1() {
InitializeComponent();
}
public UserControl1(Foo arg) : this() {
// Do something with arg
//...
}
Of course, the client code has to create that user control itself. Favor properties to keep the user control useful in the designer. Throw an exception in OnLoad() if DesignMode is false and you're not happy about the way the client code used your control.

Related

MVVM: Provide a service to work with a specific part of the UI?

let's say that in my application, there is an user interface for representing a (geographic) map. It is integrated into the application as a UserControl and has its view model behind it.
Now, suppose I want to provide other parts of my application with a generic service interface to perform common tasks on the map (zoom, pan etc.) and not worry about the UI specifics. I could give away direct reference to the viewmodel, but I am pretty sure I would violate separation of concerns principle, not to mention it would be less testable.
So there are few questions:
Does it make sense and is it good practice to implement such services (which act as an intermediate link to the UI) in the first place?
Since the service operates directly on the map's viewmodel, should it be the viewmodel itself which implements the service interface?
Is it appropriate for the service interface to provide events (e.g. besides providing a method to change the map scale, provide an event that the map scale was changed as well)? Or is it preferable to employ some kind of event broadcaster (aggregator) mechanism to push such notifications out of service interfaces?
Thanks in advance for your help.
Consider using the Messenger in the MVVM Light toolkit. See more in another SO answer:
https://stackoverflow.com/a/2700324/117625
EventAggregator is the another mechanism which establish communication between disconnected view models. I believe all the other parts of your application will be using the same MVVm and will have viewmodel to do the operations. Publish event say Zoom with required arguments from other parts of the app and catch it in the map using the subscribe mechanism.
http://msdn.microsoft.com/en-us/magazine/dd943055.aspx#id0420209
Prism has a good implementation of Event Aggregator. you can use that part.
Whenever you need two view models to communicate (or something similar, such as a button that wants to invoke a command on a view model other than its own), the best practice I've found is use a messaging channel. (MVVM Light has the Messenger class; Prism and Caliburn.Micro both have an EventAggregator.) When the target of the command is instantiated (your map view model), it will register for specific commands on a messaging channel. When an invoker (such as a button) is instantiated, it can then send commands over that same channel. This keeps your components loosely coupled. Commands from the messaging channel can be easily mocked for unit testing. It also opens up other avenues to you, such as having multiple maps open at the same time (simply use a different messaging channel or some sort of token).
I'd skip the whole service interface in your case. When using an event aggregator, it doesn't really add much. Depending on the size and complexity of your code base, you might want to keep it around so it describes the commands available for a map, but that only makes sense if you have more than a handful of commands. In that case the service would register as the end point for commands on the messaging channel and would then have to forward those commands on to a map view model. (See? Doesn't add much and only seems to complicate things.)
Skip the events. They don't seem to add anything.
What if you had an aggregate Command object which specified the appropriate behaviour? I'm going to try to flesh your question out a little bit to specifics, correct me if I'm wrong:
Let's suppose that there are two relevant parts of your app - a map component, which can be zoomed and panned etc, and a set of controls, which present the user interface for zooming, panning and selecting between them - sort of a set of mode selectors. You don't want either of them to have a direct reference to the other, and the temptation is to have the map know directly about its set of controls, so that it can catch events from them and switch mode state appropriately.
One way to take care of this would be to have a set of CompositeCommands (available from the Prism Application Guidance) libraries inside an object injected into each of them. That way you get decoupling and a strong description of interface (you could also use events if you were that way inclined).
public class MapNavigationCommands{
public static CompositeCommand startPanning = new CompositeCommand();
public static CompositeCommand startZooming = new CompositeCommand();
public static CompositeCommand setViewbox = new CompositeCommand();
}
Your mode controls, up in the Ribbon, register with your DI framework to have that injected (not wanting to introduce DI into this example, I've just referenced these static members directly).
public class ModeControls : UserControl{
...
public void PanButtonSelected(object sender, RoutedEventArgs e){
MapNavigationCommands.StartPanning.Execute(this); //It doesn't really care who sent it, it's just good event practice to specify the event/command source.
}
}
Alternatively, in XAML:
...
<Button Command={x:Static yourXmlns:MapNavigationCommands.StartPanning}>Start</Button>
...
Now, over on the map side:
public class PannableMapViewModel{
public PannableMapViewModel(){
MapNavigationCommands.StartPanning.RegisterCommand(new DelegateCommand<object>(StartPanning));
MapNavigationCommands.SetViewbox.RegisterCommand(new DelegateCommand<Rectangle>(SetViewBox));
}
private void StartPanning(object sender){
this.SetMode(Mode.Pan); //Or as appropriate to your application. The View is bound to this mode state
}
private void SetViewbox(Rectangle newView){
//Apply appropriate transforms. The View is bound to your transform state.
}
}
Now you have a decoupled, strongly specified interface between two controls, maintaining ViewModel separation, which can be mocked out for your tests.

viewmodel have to be public. How should I deal with that?

Pretty much it summarizes my problem here:
Double check - does it ever make sense to have internal viewmodel class?
I have controls.DLL and I'd like to keep this custom control bindings and viewmodel's internal. However, this doesn't seem to be possible.
How do you get around that? The only way I see it - don't use bindings..
Why do you have a view model for a custom control? I assume you're assigning the view model object to the DataContext property, but this is almost always a mistake: the DataContext should be available to consumers to use and abuse as they please. Stated another way, what happens if a consumer of your custom control explicitly sets the DataContext? It sounds like your control will stop working and throw a bunch of xaml binding errors.
A custom control is inherently lookless. There is no model or view model, just a view. That view is the .cs file. You supply a default look via your themes/generic.xaml file, but consumers should be able to supply their own template. If you're tying them to a view model, they also need to know how to create a view model instance and all of its dependencies. You've just created highly coupled code. DI containers can loosen the coupling, but that just downgrades the relationship between classes from "coupled" to "related". I say, why do consumers even need to know that information?
A better approach is to provide all of the properties for your control as dependency properties. Then your generic.xaml can provide a control template that uses the more efficient TemplateBinding to bind properties/objects to your control. If you need to populate these dependency properties from a business object, expose another dependency property of type IBusinessObject and set the derived values in that object's PropertyMetaData changed handler. If your IBusinessObject type contains a property which is yet another class which implements INotifyPropertyChanged, you should probably (1) rethink your object graph or (2) create a Bnding object in code using the subclass.
I think following all of the above advice will eliminate the problem about which you're concerned plus the other problems as well. Leave the view models to the UserControls. And yes, this is why custom controls are a MASSIVE headache. Doing them right is fairly involved.
Try protected internal. I suppose this should work. Although I don't think its good idea to have the ViewModel not public at all, cause one of the purposes of it is to be able to define several Views against the same ViewModel, which may come from different assemblies.

Custom property dependant on other properties

Advance apologies for the event-style explanation; there's a lot of factors that I feel all play a role of their own. WPF is not my native framework of choice, and it probably shows. :)
Old situation: I had a window with several controls. Depending on their selections, I used multibindings and a converter to determine whether certain controls needed to be shown that inform the user about the implications of their changes before they'd eventually confirm them by OK (or simply dismissed by using Cancel). This worked perfectly.
Problem: Too many controls as time went by, too much clutter.
Solution: Put stuff in different Pages so it becomes easier to browse for the user. In order to have changes-to-be persist as a user arbitrarily browses between the pages, I create these dynamically and put them in a cache (Dictionary<string, BasePage>, see below), from which they will be pulled as the user chooses them.
Consequence: I need to decouple the bindings to the notification controls as the different options are now on different pages.
Solution? I put a BasePage class in that exposes certain abstract read-only properties that define the various aspects that the window needs to know about in order to do its notifications. For example, a bool requiresReboot property defines whether the current state of things on that page requires a reboot to take (full) effect. A specific page implements the property based on its controls.
Problem: I do not know how to keep create a proper binding that properly gets updated as the pages are changed. I tried giving my notification controls a binding to the Dictionary<string, BasePage> with a converter that checks all pages and the relevant property.
Questions:
1) How do I create a proper property for this purpose? I presume I need a DependancyProperty as I did a fair bit of reading on MSDN, but I can't figure out how this fits together.
2) How do I make a link between my custom property so that it allows (multiple) control(s) on a page to change that property? Do I use INotifyPropertyChanged somehow? My old example bound against several CheckBox.IsChecked properties in XAML. I am trying to avoid putting tons of events (OnChange, etc) on the controls as the original code did not need it and I have been told it makes for a messy solution for as far WPF is concerned.
3) Finally, I suspect I may need to change my Dictionary<string, BasePage> class to a custom implementation that implements some sort of INotifyPropertyChanged but for Collections? Observable Collection is the term I am looking for, I believe.
I hope someone is able to bridge the gap in my understanding of WPF (property) internals; I would very much appreciate it. A basic sample would be even better, but if it is too complicated, just a nudge in the right direction will do. Thank you. :)
It's been a while since I solved this, and while I cannot remember the exact cause of the problems, there were a few different issues that made up the bulk of the trouble I ran into.
I ended up making the Property in question a non-abstract DependencyProperty in the base class; it was the only way in which I could properly delegate the change notifications to the interface. Derived classes simply ended up binding it to their controls (with a proper Converter in the case extra logic was necessitated).
As Dictionary<string, BasePage> does not support any sort of change notification, I made an extra collection of ObservableCollection<BasePage> which I used for binding purposes.
However, such a collection does not propagate a change event when items inside of it has a property changed. Since this situation required that, and I was binding to the collection itself in the context of a property that does not have a Master<->Detail relationship like a DataGrid (which basically add their own OnPropertyChanged handlers to the binded object), I ended up subclassing a VeryObservableCollecton<>. This one listens to its own items, and throws a proper change event (I think it was an OnPropertyChanged from the INotifyPropertyChanged interface) so that the binding (or in this case a multi-binding) would refresh properly and allow my interface to update.
It is hardly the prettiest code, and it feels over-engineered, but at least it allows me to properly bind the UI to the data in this manner.

Is it possible for the View to subscribe ViewModel CLR event?

Sometimes a view model needs to raise notifications, that a view should handle and do something in response, esp. when these can't be modeled as properties and property change notifications.
Anything in MVVM Light that can allow the view to listen to events and translate view model notifications into user interface actions via declarative Xaml markup?
Personally I find the technique of raising events from the VM and catching them in the view acceptable in certain circumstances. I typically prefer to work with the Messenger for such occasions though, especially if you need custom event args (because it is quite a lot of work to declare a new event args class and a new delegate).
Also, the event handler is a tight coupling between view and viewmodel, while you would typically prefer a loose coupling, but if you are aware of that fact and of the consequences, then why not...
Another technique (for example for navigation, dialogs etc) is to declare an interface with the methods you need (for example IDialogService with AskConfirmation and ShowMessage methods). Then have a class implement that interface (that can be the MainWindow/MainPage itself) and pass it to the ViewModel (for example in the View's constructor right after InitializeComponent was called). In the VM, call these methods when needed. This has the advantage of being quite easy to test (simply mock the IDialogService and check that the methods are called).
I typically move between Messenger and IDialogService depending on various factors. I tend to favor the interface based approach lately though, because it is a little easier to test (but the Messenger is quite testable too so YMMV).
Cheers,
Laurent
In a "pure" MVVM solution, the only thing that should connect the View to the ViewModel is Bindings. There is nothing stopping you from casting your DataContext to your ViewModel type and hooking an event in the view, but it kind of defeats the purpose of using the MVVM approach. As an alternative, try to rethink of why you think you need to raise an event to the view:
Need to display a popup? Some variety of bound list of "popup notifications" can be used, with a proper template, to create popups on the view as the viewmodel "inserts" notification objects into the bound collection.
Need to force a drop down open, or some similar UI action? Bind the appropriate property on the UI to a view model property, set the mode to two-way, and set as appropriate on the view model.
etc, etc.
You are right that sometimes the ViewModel needs to communicate with the View. One way to do this is that the ViewModel raises a CLR event which the View listens to. This can be done in the code-behind of the View.
MVVM is not about eliminating the code-behind of the Views! It’s about separation of concerns and improving the testability with unit tests.
Another way to enable the communication between the ViewModel and the View is by introducing an interface (IView). More information about this approach can be found on the WPF Application Framework (WAF) project site.
There is indeed a supported technique in MVVMLight for handling sending Messages from your ViewModel to your View. Look inside the GalaSoft.MvvmLight.Messaging namespace. There is a better way to send dialod messages then the below sample, however this is just a quick example.
Example
ViewModel
public MainPageViewModel()
{
Messenger.Default.Send("Payment");
}
View
public MainPage()
{
Messenger.Default.Register<string>(this, DialogRequested);
}
private DialogRequested(string message)
{
MessageBox.Show(message);
}

Is Dependency Injection possible with a WPF application?

I want to start using dependency injection in my WPF application, largely for better unit testability. My app is mostly constructed along the M-V-VM pattern.
I'm looking at Autofac for my IoC container, but I don't think that matters too much for this discussion.
Injecting a service into the start window seems straightforward, as I can create the container and resolve from it in App.xaml.cs.
What I'm struggling with is how I can DI ViewModels and Services into User Controls? The user controls are instantiated via XAML markup, so there's no opportunity to Resolve() them.
The best I can think of is to place the container in a Singleton, and have the user controls resolve their ViewModels from the global container. This feels like a half-way solution, at best, as it still required my components to have a dependency on a ServiceLocator.
Is full IoC possible with WPF?
[edit] - Prism has been suggested, but even evaluating Prism seems like a big investment. I'm hoping for something smaller.
[edit] here's a code fragment where I'm stopped
//setup IoC container (in app.xaml.cs)
var builder = new ContainerBuilder();
builder.Register<NewsSource>().As<INewsSource>();
builder.Register<AViewModel>().FactoryScoped();
var container = builder.Build();
// in user control ctor -
// this doesn't work, where do I get the container from
VM = container.Resolve<AViewModel>();
// in app.xaml.cs
// this compiles, but I can't use this uc,
//as the one I want in created via xaml in the primary window
SomeUserControl uc = new SomeUserControl();
uc.VM = container.Resolve<AViewModel>();
It's actually very easy to do. We have examples of this in Prism as jedidja mentioned. You can either have the ViewModel get injected with the View or the View get injected with the ViewModel. In the Prism StockTraderRI, you will see that we inject the View into the ViewModel. Essentially, what happens is that the View (and View interface) has a Model property. That property is implemented in the code-behind to set the DataContext to the value, for example: this.DataContext = value;. In the constructor of the ViewModel, the View gets injected. It then sets View.Model = this; which will pass itself as the DataContext.
You can also easily do the reverse and have the ViewModel injected into the View. I actually prefer this because it means that the ViewModel no longer has any back reference to the view at all. This means when unit-testing the ViewModel, you don't have a view to even Mock. Additionally, it makes the code cleaner, in that in the constructor of the View, it simply sets the DataContext to the ViewModel that was injected.
I talk a bit more about this in the video recording of the Separated Presentation Patterns talk that Jeremy Miller and I gave at Kaizenconf. The first part of which can be found here https://vimeo.com/2189854.
I think you've hit on the issue. The controls need to be injected into their parent rather than created declaratively through XAML.
For DI to work, a DI container should create the class that is accepting dependencies. This means that the parent will not have any instances of the child controls at design time and look something like a shell in the designer. This is probably the recommended approach.
The other "alternative" is to have a global static container called from the control's constructor, or something similar. There is a common pattern in which two constructors are declared, one with a parameter list for constructor injection and the other without parameters that delegates:
// For WPF
public Foo() : this(Global.Container.Resolve<IBar>()) {}
// For the rest of the world
public Foo(IBar bar) { .. }
I would almost call this an antipattern but for the fact that some frameworks leave no other choice.
I'm not even half an expert in WPF, so I'm expecting a healthy serving of downmod here :) but hope this helps. The Autofac group (linked from the homepage) might be another place to ask this question. The Prism or MEF sample apps (which include some WPF examples) should give you an idea of what is possible.
We are experiencing a similar issue. We are looking forward for a solution that will provide Design time support under Expression Blend 2.0 (Strong Type). Plus we are looking forward for a solution to have some Mock+Auto-Generated data sample available under Expression Blend.
Of course, we are looking also to have all those thing work using an IOC pattern.
Paul Stovell as an interesting article to start with:
http://www.paulstovell.com/blog/wpf-dependency-injection-in-xaml
So I try a couple thing to add more valuable design time support for Binding and mocking object at Design time, right now I’m having most of my problem related to get a strong typed connection made between the View (code) to the ModelView(Xaml), I tried a couple scenario:
Solution 1 : Using Generic to create the View
public class MyDotNetcomponent<T> : SomeDotNetcomponent
{
// Inversion of Control Loader…
// Next step add the Inversion of control manager plus
// some MockObject feature to work under design time
public T View {Get;}
}
This solution does not work since Blend does not support Generic inside is design surface but Xaml do have some, well work at runtime but not at design;
Solution 2: ObjectDataProvider
<ObjectDataProvider ObjectType="{x:Type CP:IFooView}" />
<!-- Work in Blend -->
<!—- IOC Issue: we need to use a concrete type and/or static Method there no way to achive a load on demande feature in a easy way -->
Solution 3: Inherit ObjectDataProvider
<CWD:ServiceObjectDataProvider ObjectType="{x:Type CP:IFooView}" />
<!-- Cannot inherit from ObjectDataProvider to achive the right behavior everything is private-->
Solution 4: Create a mock ObjectDataProvider from scratch to the job
<CWD:ServiceObjectDataProvider ObjectType="{x:Type CP:IFooView }" />
<!-- Not working in Blend, quite obvious-->
Solution 5: Create a Markup Extension (Paul Stovell)
<CWM:ServiceMarkup MetaView="{x:Type CP:IFooView}"/>
<!-- Not working in Blend -->
Just to clear one point. When I said “not working in blend”, I mean that the Binding dialog is not usable and the designer needs to handwrite the XAML by itself.
Our next step will probably be to take the time to evaluate the ability to create a plug-in for Expression Blend.
Yes, we do it all the time. You can "inject" your ViewModel into the DataContext of the control.
I actually find WPF being even easier to use with DI. Even the dependency objects and properties work with it seamlessly.
You should take a look at Caliburn - it's a simple WPF/Silverlight MVC framework with support for full DI. It looks really cool and it lets you use any IoC container you want. There are a couple of examples on the documentation wiki
Glen Block (see above) mentions that a common approach is to design your MVVM solution to use the DataContext as the place where you can "resolve" your View Model in the View. Then you can use design extensions from expression blend 2008 (note that you don't need to be using the expression blend design tools to take advantage of this). For example:
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DataContext="{d:DesignInstance Type=local:MyViewModelMock, IsDesignTimeCreatable=True}"
In your view you can have a property getter that casts your DataContext to the type that you expect (just to make it easier to consume in the code-behind).
private IMyViewModel ViewModel { get { return (IMyViewModel) DataContext; } }
Don't forget to use an interface so that your views are easier to test, or to help you inject different runtime implementations.
In general, you should not be resolving things from the container all over the place in your solution. It is actually considered bad practice to pass your container around in every constructor, or to make it globally accessible. (You should look up discussions of why "Service Locator" strategies constitute an "Anti-Pattern").
Create a public View constructor with explicit dependencies that the container (e.g. Prism Unity or MEF) can resolve.
If necessary, you could also create an internal default constructor to create a mock of your view model (or a real one for that matter). This protects against inadvertent use of this "design constructor" externally (in your "Shell" or wherever). Your test projects can also use such constructors using the "InternalsVisibleToAttribute" in "AssemblyInfo". But of course, that usually isn't necessary since you can inject your mocks using the full dependency constructors anyway, and because the majority of your tests should be focusing on the ViewModel in the first place. Any code in the View should ideally be quite trivial. (If your View requires a lot of testing, then you might want to ask yourself why!)
Glen also mentions that you can inject Views into View Models, or View Models into Views. I much prefer the latter because there are perfectly good techniques for decoupling everything (use of Declarative Binding, Commanding, Event Aggregation, Mediator patterns, etc.). The View Model is where all the heavy lifting will be done to orchestrate core business logic. If all of the necessary "binding" points are provided by the View Model, it really shouldn't need to know ANYTHING about the View (which can mostly be wired up to it declaratively in the XAML).
If we make the View Model agnostic to the source of user-interaction, that makes it much easier to test (preferably first). And it also means that you can easily plug in ANY view (WPF, Silverlight, ASP.NET, Console, etc.). In fact, to ensure that appropriate decoupling has been achieved, we can ask ourselves if a "MVM" (Model-ViewModel) architecture could work in the context of, say, a Workflow service. When you stop to think about it, most of your unit tests will probably be designed on that premise.
I think You have to Decide on View First or Viewmodel First then as given the other answer it Can be decide.. There are several open source framework does it same . I use Caliburn where ViewModel first is taken and its really good approach
I wrote an very light framework where a ViewModel is resolved at runtime by using a IoC (Unity) as a markup extension.
The framework allows for writing XAML without a code behind but still lets you have routed commands, data binding, and event handlers.
In any case, I don't think you need the loose XAML in your case, but if you look at the code (http://xtrememvvm.codeplex.com), it might turn out that you can use some of the code to solve your own issues with injecting View Models and Services.

Resources