WPF - 使用具有多个 ViewModel 的单个模型
Posted
技术标签:
【中文标题】WPF - 使用具有多个 ViewModel 的单个模型【英文标题】:WPF - Use a single Model with multiple ViewModels 【发布时间】:2016-01-04 10:19:09 【问题描述】:如何允许多个视图模型共享同一个模型?
我正在 ApplicationViewModel 中创建视图模型,该视图模型用于使用带有所选 VM 的 DataTemplate 在视图之间切换。
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"];
我希望能够从每个创建的 VM 中访问相同的 Data 类。 理想情况下,我会使用参数将 Data 类传递给每个 ViewModel,但这会导致在 XAML 中设置 DataContex 引发错误,因为 DataContext 没有可访问的构造函数。
更新
我在其他视图中设置 DataContext,如下所示:
<UserControl.DataContext>
<viewModels:SummaryViewModel/>
</UserControl.DataContext>
但这样做会创建一个新的 ViewModel 实例,而不是使用绑定到 CurrentBasePageViewModel
的实例。
【问题讨论】:
您是否考虑过拥有 ContentControl? 这就是我改变视图的方式。该窗口有一个侧边菜单和一个 ContentControl,其内容绑定到选定的 VM。 对不起,我没有仔细阅读帖子。您可以尝试跟随 - 或通过参数传递信息,或编写静态类或实现接口 或者您可以在加载到 currentBasePageViewModel 之前通过属性将参数从应用程序视图模型设置为基本页面视图模型 那我该如何设置DataContext呢?从视图的 XAML 中设置它会创建一个新的 VM 实例。 【参考方案1】:当然,解决方案是将模型传递给 viemodel 的构造函数。
现在,如何用 xaml 解决您的问题?
首先,从您的问题和发布的代码中不清楚,有什么问题。 (缺少 xaml 代码)。
我只是猜测,问题是导致设计时数据上下文,因为它需要无参数构造函数。有两种解决方案:
添加无参数构造函数:
public class MyViewModel
public MyViewModel()
//design time ctor. Create design time data here
public MyViewModel(MyModel model)...
为设计时数据上下文创建新类:
public class MyViewModelDesignTime : MyViewModel
public MyViewModelDesignTime() : base(new MyModel())
//design time ctor. Create design time data here
并在 xaml 中使用此类:
d:DataContext="d:DesignInstance l:MyViewModelDesignTime, IsDesignTimeCreatable=True"
【讨论】:
我已经更新了问题。创建一个无参数的构造函数会导致 View 使用它创建一个新的 VM,从而使模型为空。 如果您在 applicationviewmodel 中创建了 viewmodel,则无法在 xaml 中创建它,因为您将拥有同一类的两个不同实例。 ContentPresenter 自动设置数据上下文。尝试用谷歌搜索 xaml 隐式数据模板 知道我遗漏了一些明显的东西。好像是这样,谢谢。【参考方案2】: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>
【讨论】:
【参考方案3】:试试这样的:
HomeViewModel _homeViewModel;
SummaryViewModel _summaryViewModel;
public ApplicationViewModel()
//Add pages
_homeViewModel = new HomeViewModel();
_summaryViewModel = new SummaryViewModel();
//some code here
_homeViewModel.SomeProperty = 5;
CurrentBasePageViewModel = _homeViewModel;
然后您的视图 homeViewModel 的一些 int 属性将具有值 5。 您还可以在 homeViewModel 中创建属性,该属性将保存对当前 ApplicationViewModel 的引用或创建接口。 接口示例:
public interface IName
/// <summary>
/// Property name.
/// </summary>
string PropertyName get;
然后让ApplicationViewModel实现这个接口并传递给viewmodel。在 viewModel 创建属性。比如:
public class HomeViewModel
IName _iName;
public HomeViewModel(IName name)
_name = name;
还有你的 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;
【讨论】:
以上是关于WPF - 使用具有多个 ViewModel 的单个模型的主要内容,如果未能解决你的问题,请参考以下文章
在 ViewModel 中具有静态 DbContext 的 WPF 应用程序
如何在 WPF 中使用多个 ViewModel 并通过一个 MainViewModel 绑定它们?
如何使 WPF DataGrid 显示具有绑定和 DataTemplate 的 ViewModel 集合
WPF C# Ninject 与 mainViewModel 和多个 viewmodel 问题
Caliburn.Micro-如何从继承的ViewModel在WPF视图中显示多个项目:Conductor 。Collection.AllActive