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 的单个模型的主要内容,如果未能解决你的问题,请参考以下文章

wpf MVVM Viewmodel之间传值

在 ViewModel 中具有静态 DbContext 的 WPF 应用程序

如何在 WPF 中使用多个 ViewModel 并通过一个 MainViewModel 绑定它们?

如何使 WPF DataGrid 显示具有绑定和 DataTemplate 的 ViewModel 集合

WPF C# Ninject 与 mainViewModel 和多个 viewmodel 问题

Caliburn.Micro-如何从继承的ViewModel在WPF视图中显示多个项目:Conductor 。Collection.AllActive