I have a winform which contains a usercontrol. That usercontrol has a dependency which I need to resolve using unity. The problem with using constructor injection is that the user control is instantiated in the InitializeComponent of the designer of the winform. Hence I cannot place container.Resolve over there.
What is the alternative?
I believe you will want to use Property Injection and BuildUp:
Using BuildUp to Wire Up Objects Not Created by the Container
Constructor injection is generally the preferred method, but as you noted it's not possible when dealing with WinForm controls.
Related
I've got a UserControl in a WPF application which has a RoutedCommand. The RoutedCommand needs to access a service that I've registered in the DI container.
The problem is that I can't figure out how to get a reference to the service so the RoutedCommand can use it.
Normally, I would just inject whatever service I need into the constructor of the ViewModel and, of course, the ViewModel would also be registered in the DI container.
In this case, however, the UserControl's DataContext is just itself (it has no separate ViewModel). I don't even explicitly instantiate the UserControl because that's handled by WPF infrastructure through a parameterless constructor. The UserControl is just items for a WPF ListBox.
I tried making a dependency property in the UserControl to hold the service, but that doesn't seem to work. Maybe I did it wrong, but I don't even know if that's the right path forward.
FWIW, I am not using any library/framework like PRISM. Is there a way to do this that I am just not seeing?
I can create views myself using IoC without any problems if all dependencies that my view constructor needs as arguments are registered within my IoC-container.
But in case if I try to extensively use DataTemplates, then WPF creates my views. And in case if view has no default constructor, then WPF will fail and crash whole app. Thus my question is - are there any extensibility points in WPF so that I can provide a view factory to it, which will be able to create my views even when they do not have default constructor?
Unfortunately, and to my knowledge, the answer is no. I was just looking for the same thing, but WPF can only create user controls with parameterless constructors.
One solution would be to use the Service Locator pattern, where your UserControl has access to the container in its constructor and Resolves its dependency by itsself. I personally don't like this pattern. Some call Service Locator an anti-pattern, and in the long run, it can get you into trouble.
We are currently in the process of switching our product from WinForms to WPF. At the moment we are using some 3rd party WinForm controls that are required for our application. Even though we plan to eventually replace them with WPF versions, right now this is not possible. We've tried hosting them in the wpf window inside WindowsFormsHost control, and it seems to work just fine. The only problem we have is how to pass our data from VM to these controls. We would like to avoid any code-behind and alterations to VM just to accomodate this controls. Ideally, we would prefer to keep VM completely unaware of the controls used to display it's data, so that when we do change to WPF version of these controls, we only need to modify the view. This is why we're looking for a way to bind VM property to hosted WinForm control from XAML. If this helps, we can certainly live with the fact that there is only a one way binding from VM to the control, and we don't mind if the binding works only once, without the subsequent updates from VM, since the VM properties we are binding do not change. Perhaps someone has any ideas how we can make this happen?
Not sure if there is a better way, but here's one idea:
Wrap your WinForm control/WindowsFormsHost control into a wrapper control (inherit from Control or use a UserControl, whatever is best for you).
On this wrapper you can add dependency properties that you want to bind to your VM.
Inside the wrapper code, you can add the boilerplate required to propagate changes back and forth between your wrapper dependency properties and your winform properties.
This hides the dirt under the carpet and exposes a nice WPF facade that you can bind to as usual, without changing your VM.
When the control is phased out, remove the wrapper from your project and you can bind the VM directly to the new WPF replacement control.
I have WinForm application with hosted in it WPF(mvvm) part. Is it possible to change dependency property in ModelView from my WinForm ?
Is it possible to change dependency property in ModelView from my WinForm ?
It is - but your Windows Forms portion would need to understand the WPF types to do it. You can always use the wrapper defined when implementing a dependency property to call it from code.
If you're hosting a Windows Forms control, however, you'll likely want to make a WPF wrapper that subscribes to the appropriate events on the control, and uses them to set the dependency property. This way, your Windows Forms portion stays "pure" and doesn't need modification, and your WPF portion can set everything appropriately.
My client is trying to hook to a usercontrols Loaded Event in the View Model. Basically they want to know when the controls loaded event triggers inside the view model. They are looking for a way to do it without code behind the xaml. Is this even feasible. I am looking into whether I can route the loaded event to the viewmodel in the xaml.
One way of doing it is to use InvokeDataCommand. You'd specify the trigger's EventName as Loaded, and then your command (defined in your VM) would execute when Loaded event is fired.
You need to look into commanding. Silverlight support is fairly weak compared to WPF but it does contain the ICommand interface. You can extend controls to give them command properties or implement them via an attached property. The commands basically invoke themselves once an action has occurred in the UI. They are totally independent of how the UI is built (or at least they should be) and so can be completely unit tested.