【问题标题】:UserControl of UIElements in ViewModel breaks MVVM?ViewModel 中 UIElements 的 UserControl 会破坏 MVVM?
【发布时间】:2015-12-15 04:48:02
【问题描述】:

我们已经为我们的 WPF 应用程序提供了一个现有的 UI,其中单独的按钮按下将显示基于绑定到可见性 (MVVM) 的元素,其中 ICommand 将设置这些可见性属性打开或关闭。这些效果很好,但最近我们被要求按下按钮来显示/隐藏元素,就像以前一样,但是另一种类型的按钮按下来显示一些其他元素,但在 TabControl 内。

我想这样做的方式是:

a) 创建包含这些元素的单独用户控件

b) 这些用户控件在运行时通过 ViewModel 实例化,具体取决于按钮按下,并通过 ObservableCollection 作为 ItemsSource 绑定到 View:

视图模型:

private ObservableCollection<Object> centerView;
public ObservableCollection<Object> CenterView
{
    get { return centerView; }

}            

...

    UserControlOfReportRelatedElements reportsView = new UserControlOfReportRelatedElements();
    CenterView.Clear();
    Grid.SetRow(reportsView, 0);
    CenterView.Add(reportsView);

XAML:

    <ItemsControl ItemsSource="{Binding CenterView}" Grid.Row="2">
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <Grid/>
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
    </ItemsControl>

因此,根据 UserControl 是否包含在 TabControl 中,我们只需将其滑入 ObservableCollection(在运行时)。

这行得通,而且很方便。但这会破坏 MVVM 吗?我们还有什么可以做的吗?

【问题讨论】:

    标签: c# wpf xaml mvvm


    【解决方案1】:

    我会说,是的,这打破了 MVVM 模式。 MVVM 背后的想法之一是保持 View (UI) 和 ViewModel (业务逻辑) 彼此分离。

    您的解决方案可能是创建一个 Base-ViewModel-Class,其中继承了不同视图(您的标签页)的 ViewModel。在您的 ObserableCollection 中,您有 Base-ViewModel-Instanced。

    要向您的视图模型显示正确的视图,您可以在 App.xaml 中执行以下操作

    <DataTemplate DataType="{x:Type viewModel:CustomViewModel1}">
       <view:CustomView1/>
    </DataTemplate>
    

    通过这个定义,您告诉您的应用程序,无论何时应该显示CustomViewModel1,都应该显示CustomView1。有了这个,DataContext 也被设置了。

    一个很好的例子是this

    【讨论】:

      【解决方案2】:

      是的,在视图模型中引用 UI 元素会破坏 MVVM。视图模型应该是完全隔离的并且不知道视图。

      解决此问题的一种方法是将实际数据内容公开为视图模型上的属性。然后,您可以使用各种机制来显示基于该内容的控件。例如,如果您公开一个对象列表,则可以使用数据模板根据对象的类型显示不同的控件。

      因此,您只需在视图模型上公开 数据,并期望视图提供正确显示该数据的必要方法。

      例如,不是公开UserControlOfReportRelatedElements 控件,而是公开包含数据的ReportData 对象。然后,您将在 ReportData 类型上注册一个数据模板,然后显示 UserControlOfReportRelatedElements 元素并显示来自 ReportData 对象的数据。

      【讨论】:

      • ContentControl 旨在与您在回答中提到的技术结合使用时,准确地支持问题所讨论的情况。
      • 我从这个答案中学到了很多,但我选择了 TomTom,因为此时它更容易实现。谢谢你。我会这样想
      • @Tyress 我实际上认为我们都指的是同一件事 ;)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-07-04
      • 2016-12-10
      • 2011-12-04
      • 2019-10-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多