【问题标题】:WPF - Use a single Model with multiple ViewModelsWPF - 使用具有多个 ViewModel 的单个模型
【发布时间】: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 实例。

标签: c# wpf mvvm


【解决方案1】:

当然,解决方案是将模型传递给 viemodel 的构造函数。

现在,如何用 xaml 解决您的问题?

首先,从您的问题和发布的代码中不清楚,有什么问题。 (缺少 xaml 代码)。

我只是猜测,问题是导致设计时数据上下文,因为它需要无参数构造函数。有两种解决方案:

  1. 添加无参数构造函数:

    public class MyViewModel {
       public MyViewModel(){
           //design time ctor. Create design time data here
       }
    
       public MyViewModel(MyModel model){...}
    }
    
  2. 为设计时数据上下文创建新类:

    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;
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2011-04-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-03-11
      • 1970-01-01
      • 1970-01-01
      • 2014-05-09
      • 1970-01-01
      相关资源
      最近更新 更多