How to I connect a ViewModel to a View when the vi

2019-02-14 08:36发布

问题:

I'm using Prism and Unity to rewrite a WPF application using the MVVM pattern. Most of the Views are connected to the VM via the DataContext property, like so:

<UserControl.DataContext>
    <VM:RibbonViewModel/>
</UserControl.DataContext>

The problem is that this method will not work when there is a parameter in the ViewModel's constructor.

public RibbonViewModel(IEventAggregator eventAggregator)
{
    this.eventAggregator = eventAggregator;
}

I get the error:

Type 'RibbonViewModel' is not usable as an object element because it is not public or does not define a public parameterless constructor or a type converter.

How do I connect the VM to the View when a parameter is there?

回答1:

You might have a look at the sample applications of the WPF Application Framework (WAF). In these examples the IoC Container (in your case its Unity) is responsible to create the ViewModels. This way a ViewModel can have constructor parameters. The IoC Container is also responsible to bring the View with the ViewModel together. Maybe this is an option for your ViewModel design as well.



回答2:

Consider using a ViewModelLocator. Rather than binding the datacontext to the ViewModel in your case above, you bind to a locator which knows how to resolve the ViewModel from the (unity) container and in the process inject any dependencies into the constructor. There's a blog posting summarizes an implementation by John Papa and Glenn Block (one of the people behind prism).

I believe the EventAggregator is registered with the container by default, so it should be auto-wired with the VM when you resolve the VM from the container.


I should mention the code from the above blog is using MEF. This blog I believe has a codeplex example using unity



回答3:

I don't use unity or prism. But, why can't you just do this:

userControl.DataContext = ribbonViewModelInstance;

You can have a dependency property on the user control which is set. On setting of value of this dependency property, you can set the datacontext.