ViewModel中UIElements的UserControl打破MVVM?

时间:2015-09-18 06:25:15

标签: c# wpf xaml mvvm

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

我想这样做的方式是:

a)创建包含这些元素的单独UserControl

b)这些UserControl在运行时通过ViewModel实例化,具体取决于按下按钮,并通过ObservableCollection绑定到View as ItemsSource:

视图模型:

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吗?我们还能做些什么吗?

2 个答案:

答案 0 :(得分:3)

我会说,是的,打破了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

答案 1 :(得分:3)

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

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

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

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