ViewModel中UIElements的UserControl破坏了MVVM
本文关键字:坏了 MVVM UserControl UIElements ViewModel | 更新日期: 2023-09-27 18:13:12
我们的WPF应用程序已经有了一个现有的UI,其中单独的按钮按下将显示基于绑定到可见性(MVVM)的元素,其中一个iccommand将设置这些可见性属性打开或关闭。这些工作得很好,但最近我们要求按下按钮来显示/隐藏元素,但另一种类型的按钮按下显示一些其他元素,但在TabControl中。
我想到的方法是:
a)创建包含这些元素的单独UserControlsb)这些UserControls在运行时通过ViewModel实例化,依赖于按钮的按下,并通过ObservableCollection作为ItemsSource绑定到View:
ViewModel:
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吗?我们还能做些什么吗?
我会说,是的,这打破了mvvm模式。MVVM背后的思想之一是保持视图(UI)和视图模型(业务逻辑)彼此分离。
您可以创建一个Base-ViewModel-Class,其中继承了不同视图(选项卡页面)的viewmodel。在ObserableCollection中,你有base - viewmodel - instance。
要在视图模型中显示正确的视图,可以在App.xaml
中执行以下操作<DataTemplate DataType="{x:Type viewModel:CustomViewModel1}">
<view:CustomView1/>
</DataTemplate>
通过这个定义,您可以告诉应用程序,只要应该显示CustomViewModel1
,就应该显示CustomView1
。这样也设置了DataContext。
是的,在视图模型中引用UI元素会破坏MVVM。视图模型应该是完全隔离的,并且不知道视图。
解决这个问题的一种方法是将实际的数据内容作为视图模型的属性公开。然后,您可以使用各种机制来显示基于该内容的控件。例如,如果您公开一个对象列表,那么您可以根据对象的类型使用数据模板来显示不同的控件。因此,您只需在视图模型上公开数据,并期望视图提供必要的方法来正确显示该数据。
例如,不是暴露UserControlOfReportRelatedElements
控件,而是暴露包含数据的ReportData
对象。然后您将在ReportData
类型上注册一个数据模板,然后显示UserControlOfReportRelatedElements
元素并显示来自ReportData
对象的数据。