Reputation: 38
I have a WPF application which implements navigation using MVVM, filling a different DataTemplate
for each View within the same Window
e.g. :
<Window.Resources>
<DataTemplate DataType="{x:Type foo:FooViewModel}">
<foo:FooView/>
</DataTemplate>
<DataTemplate DataType="{x:Type bar:BarViewModel}">
<bar:BarView/>
</DataTemplate>
<Window.Resources>
(Switching between Views/UserControls using MVVM is Rachel Lim's article which has inspired the aforementioned approach)
What happens now is that FooView gets FooViewModel automatically injected as a dependency by DI (which in my case is Microsoft.Extensions.DependencyInjection on .Net Core3 Preview) e.g. :
public partial class FooView : UserControl
{
public FooView(FooViewModel fooViewModel)
{
this.InitializeComponent();
this.DataContext = fooViewModel;
}
}
At this point obviously the DataTemplate complains because the FooView does not define a parameter-less ctor (as per reference Type '{0}' is not usable as an object element)
Is there any way to bypass this issue and let FooView to use FooViewModel as DataContext?
Upvotes: 1
Views: 1560
Reputation: 35679
DataTemplate
<DataTemplate DataType="{x:Type foo:FooViewModel}">
<foo:FooView/>
</DataTemplate>
will assign an instance of FooViewModel to FooView.DataContext.
this.DataContext = fooViewModel;
line in FooView
control is useless, because DataContext will be overwritten in such scenario. I would say, it is perfectly fine not to pass view model via contrustor. It can be accessed from DataContext:
public partial class FooView : UserControl
{
public FooView()
{
this.InitializeComponent();
}
private FooViewModel Vm { get { return this.DataContext as FooViewModel; } }
}
In the navigation pattern you are using, View is a receiver of ViewModel. Current ViewModel is set by AppViewModel
:
public class AppViewModel
{
// simplified properties
public ViewModelBase CurrentViewModel {get; set;}
public ICommand ViewFooCommand {get;}
public ICommand ViewBarCommand {get;}
}
You are trying to make View an originator/producer of ViewModel, which conflicts with pattern.
Upvotes: 2