Reputation: 457
How would you allow multiple viewmodels to share the same model?
I'm creating the viewmodels in an ApplicationViewModel that is used for switching between views using a DataTemplate with the selected VM.
public ApplicationViewModel()
{
//Add pages
BasePageViewModels.Add("Home Page", new HomeViewModel());
BasePageViewModels.Add("Summary Page", new SummaryViewModel());
BasePageViewModels.Add("AddTestRun Page", new AddTestRunViewModel());
//some code here
CurrentBasePageViewModel = BasePageViewModels["Home Page"];
}
I want to be able to access the same Data class from within each of the created VM's. Ideally I'd pass in the Data class to each ViewModel with a parameter but that then causes setting DataContex within XAML to throw an error because the DataContext has no accessible constructors.
Update
I'm setting the DataContext in the other Views like so:
<UserControl.DataContext>
<viewModels:SummaryViewModel/>
</UserControl.DataContext>
but doing that creates a new instance of the ViewModel, rather than using the one bound to CurrentBasePageViewModel
.
Upvotes: 1
Views: 3516
Reputation: 27328
Definitelly, the solution is to pass model to viemodel's constructor.
Now, how to solve your problem with xaml?
First of all, from your question and posted code it is not clear, what's the problem. (the xaml code is missing).
I just guess, the problem is causing design time datacontext, since it requires parameterless constructor. There are two solutions:
Add parameterless constructor:
public class MyViewModel {
public MyViewModel(){
//design time ctor. Create design time data here
}
public MyViewModel(MyModel model){...}
}
Create new class for design time datacontext:
public class MyViewModelDesignTime : MyViewModel {
public MyViewModelDesignTime() : base(new MyModel()){
//design time ctor. Create design time data here
}
}
and use this class in xaml:
d:DataContext="{d:DesignInstance l:MyViewModelDesignTime, IsDesignTimeCreatable=True}"
Upvotes: 1
Reputation: 853
try something like this:
HomeViewModel _homeViewModel;
SummaryViewModel _summaryViewModel;
public ApplicationViewModel()
{
//Add pages
_homeViewModel = new HomeViewModel();
_summaryViewModel = new SummaryViewModel();
//some code here
_homeViewModel.SomeProperty = 5;
CurrentBasePageViewModel = _homeViewModel;
}
Then some int property of your view homeViewModel will have value 5. Also you can create property in homeViewModel that will hold reference to current ApplicationViewModel or create interface. Example of the interface:
public interface IName
{
/// <summary>
/// Property name.
/// </summary>
string PropertyName { get; }
}
Then make ApplicationViewModel implement this interface and pass it to viewmodel. In viewModel create property. Something like:
public class HomeViewModel
{
IName _iName;
public HomeViewModel(IName name)
{
_name = name;
}
}
And your ApplicationViewModel:
public class ApplicationViewModel : IName
{
HomeViewModel _homeViewModel;
SummaryViewModel _summaryViewModel;
public ApplicationViewModel()
{
//Add pages
_homeViewModel = new HomeViewModel(this);
_summaryViewModel = new SummaryViewModel();
//some code here
_homeViewModel.SomeProperty = 5;
CurrentBasePageViewModel = _homeViewModel;
}
}
Upvotes: 0
Reputation: 21241
public ApplicationViewModel()
{
//shared model
var model = new MyModel();
//Add pages
BasePageViewModels.Add("Home Page", new HomeViewModel(model));
BasePageViewModels.Add("Summary Page", new SummaryViewModel(model));
BasePageViewModels.Add("AddTestRun Page", new AddTestRunViewModel(model));
//some code here
CurrentBasePageViewModel = BasePageViewModels["Home Page"];
}
<UserControl x:Class="ApplicationView"
xmlns:vm="clr-namespace:MyApp.ViewModels"
xmlns:vw="clr-namespace:MyApp.Views">
<UserControl.Resources>
<DataTemplate DataType="{x:Type vm:HomeViewModel}">
<vw:HomeView />
</DataTemplate>
<DataTemplate DataType="{x:Type vm:SummaryViewModel}">
<vw:SummaryView />
</DataTemplate>
<DataTemplate DataType="{x:Type vm:AddTestRunViewModel}">
<vw:AddTestRunView />
</DataTemplate>
</UserControl.Resources>
<ContentControl Content={Binding CurrentBasePageViewModel} />
</UserControl>
Upvotes: 0