【问题标题】:Reusing views for multiple view models为多个视图模型重用视图
【发布时间】:2016-01-21 14:13:50
【问题描述】:

我想为 2 个不同的视图模型重用一个视图,在我的示例中是 MyEntityEditViewModelMyEntityCreateViewModel。视图基本上只是一个带有Save 按钮的表单,非常常见的布局。

我创建了两个视图模型以及父视图/视图模型 (MyEntitySummaryViewModel),现在我想使用 ContentControl 定义 form 视图。

概要视图

<ContentControl x:Name="ActiveItem" cal:View.Model="{Binding ActiveItem}" cal:View.Context="MyEntityDetailView" />

MyEntitySummaryViewModel

public MyEntity SelectedEntity {
    get { return _selectedEntity; }
    set {
        _selectedEntity = value;
        NotifyOfPropertyChange();

        ActivateItem(new MyEntityEditViewModel(_selectedEntitity));
    }
}

public void Create() {
    ActivateItem(new MyEntityCreateViewModel(new MyEntity()));
}

我的问题现在是 Caliburn 尝试定位“MyEntityEditView”,因为它的视图定位约定,即使我严格将 ContentControl 的上下文定义为自定义视图。有没有解决的办法?还是我在这里做错了什么?

【问题讨论】:

  • 从未尝试过caliburn,但有data templates 分配视图。将相同的视图分配给两个视图模型。
  • 在这种情况下不需要两个视图模型。为它创建一个视图模型或一个局部视图,然后在 createview 或 editview 上渲染该局部视图..
  • @Sinatr 谢谢,但我的基础是 CM。当没有其他解决方案时,我正在考虑围绕框架工作。 :)
  • @PankajGupta 部分浏览?在 WPF 中?好吧,我可以通过创建一个额外的视图/视图模型作为包装器在技术上“模拟”它们,但我希望有一个开销更少的解决方案。 =)

标签: c# .net wpf mvvm caliburn.micro


【解决方案1】:

如果我的理解是正确的,您希望 2 种 ViewModel 指向同一个视图。如果是这样,只需为您的实体 (EntityBaseViewModel) 创建一个基类并创建一个视图 (EntityBaseView)。

要绑定 ContentControl,请设置他的 x:Name,以便名称与您的 ViewModel 的属性相匹配。

例子:

视图(ShellView):

<ContentControl x:Name="SelectedEntity"/>

视图模型(ShellViewModel):

public EntityBaseViewModel  SelectedEntity 
{
    get 
    { 
        return this._selectedEntity; 
    }
    set 
    {
        this._selectedEntity = value;
        this.NotifyOfPropertyChange(() => SelectedEntity);
    }
}

如果您确实按照您所说的命名约定创建了 ViewModel / View,Caliburn 将为 ViewModel 找到 View 并绑定 DataContext。

【讨论】:

    【解决方案2】:

    聚会有点晚了,但也许这会对某人有所帮助。这个视频对我很有帮助 - (Tim Corey, WPF and Caliburn with MVVM)

    如您所述,使用指向 ActiveItem 的控件设置 ShellView,允许该控件显示您从 ShellViewModel 代码中告诉它的任何视图。我也在这个项目中使用了 Fody,所以它处理了更改通知,所以你不会看到代码中列出的那些。

    ShellView -

    <Button x:Name="LoadMainPage" />    
    <Button x:Name="LoadSecondPage" />
    <ContentControl x:Name="ActiveItem"/>
    

    ShellViewModel -

    public class ShellViewModel : Conductor<object>.Collection.OneActive
    {       
            public MainPageViewModel MainPageVM = new MainPageViewModel();
            public SecondPageViewModel SecondPageVM = new SecondPageViewModel();
    
            public ShellViewModel()
            {           
                LoadMainPage(); // auto load main page on startup
            }
    
            public void LoadMainPage()
            {
                ActivateItem(MainPageVM);
            }
    
            public void LoadSecondPage()
            {
                ActivateItem(SecondPageVM);
            }
    }
    

    在使用 ActivateItem 时,您无需创建 ViewModel 的新实例,而是重新使用创建的初始实例。或者,如果您更愿意在每次启动特定视图时创建另一个实例,那么只需使用已有的 ActivateItem。

    在您的 SecondPageViewModel 中为视图,它将占用 ActiveItem 的 ContentControl 中的空间 -

    public class SecondPageViewModel : Screen
    

    SecondPageView.xaml 添加为用户控件(以及您要创建的任何其他子/子视图)-

    <UserControl x:Class="MyNamespace.Views.SecondPageView"
                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
                 xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
                 xmlns:local="clr-namespace:MyNamespace.Views"
                 mc:Ignorable="d" 
                 d:DesignHeight="450" d:DesignWidth="800">
        <Grid>
    
        </Grid>
    </UserControl>
    

    这将允许您在基本视图/视图模型的任何视图之间来回切换,并显示您在 ContentControl 框中选择的子视图的内容(无论您想要多少)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-10-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多