何时将View与ViewModel分开?

时间:2014-02-26 22:40:46

标签: c# wpf mvvm

所以我正在开发一个GUI,其中大部分是用1个窗口实现的,并使用该窗口的代码隐藏来处理大部分逻辑。该程序是由GUI驱动的。假设有一个组合框,如果从组合框中选择一些内容,则数据会发生显着变化,所有其他GUI框/标签/网格也会发生变化或清除等。

我正在进行大量重构,并且我已经了解MVVM,但我从未真正看到它的需要。我理解它的用途和原因,但功能更容易直接从我发现的代码中引用所有GUI组件。

例如......

在我的主窗口中我有

<ComboBox x:Name="MyTitlesUI" ItemsSource="{Binding Titles}" SelectionChanged="MyTitlesUI_SelectionChanged">

所以ComboBox与我的MainWindowViewModel中的List Titles相关联吗? MyTitlesUI_SelectionChanged事件应该去哪里?它需要在视图中正确吗?但是,如果SelectionChanged的功能与MainWindowViewModel中的数据有关怎么办?

假设您更改了MyTitlesUI中的选择,现在程序必须在数据库中查找该标题字符串。所有这些数据库功能都在您在MainWindowViewModel中声明的DBClass中。你如何访问该功能?你为什么要这样做:

在主窗口cs中:

private void MyTitlesUI_SelectionChanged(object sender, EventArgs e)
{
   viewModel.ConnectToDataBase((string)MyTitlesUI.SelectedItem);
}

在MainWindowViewModel.cs

private SelectedTitle;
public void ConnectToDataBase(string title)
{
  SelectedTitle = title;
  DBClass myDB = new DBClass(SelectedTitle);
  .... //do stuff with myDB
 }

那似乎有点不必要吗?这当然只是一个温和温和的例子,也许看起来很干净。但是如果你在View和ViewModel之间做了非常复杂的反向和第四,那么ViewModel中可能需要在View中对MyTitlesUI.SelectedItem的引用,因为其他函数可以工作,因此是SelectedTitle私有变量。

现在你有更多的任务,更多的变量,更多的函数只是调用其他函数,而不仅仅是一个简单的MyTitlesUI.SelectedItem来处理。

为什么不将DBClass引用带到View或类似的? 特别是如果您正在进行大量的UI操作,那么ViewModel中的信息将会被播放。说一旦我改变标题的选择,我需要图表清除。但是我的图表在我的ViewModel连接到数据库之后才能清除。

我将在我的View中定义图形或网格,这些图形或网格依赖于我的ViewModel中需要更新的动态创建的数据。我正在尝试将View中需要的内容和ViewModel中需要的内容包装起来。从ViewModel引用View似乎不合适,因此无法在ViewModel中调用类似MyTitlesUI.SelectedItem的内容。

编辑:

回到Selected Item示例,假设我有一个Treeview UI项。我想将它绑定到我还没有的Treeview。我使用DB connect为程序创建数据。因此,用户从组合框中选择他们想要的标题。然后,Db Connect以某种数据结构异步创建TreeviewItem。

private SelectedTitle;
public void ConnectToDataBase(string title)
{
  SelectedTitle = title;
  DBClass myDB = new DBClass(SelectedTitle);

  if(myDB.doneWorking)
  {
    myTreeView.ItemsSource = myDB.GetTree();
  }

 }

1 个答案:

答案 0 :(得分:4)

  

但功能更容易引用所有GUI组件   直接从我发现的代码

错误。 MVVM提供了一种基于属性的简洁方法,比txtPepe_TextChanged()类似winforms的方法更容易使用。尝试更改隐藏在Text内的TextBlock的{​​{1}},该DataTemplate用作虚拟化ItemTemplate的{​​{1}},后面使用代码... WPF不是winforms。

  

MyTitlesUI_SelectionChanged事件应该去哪里?

无处。 MVVM最适合使用基于属性/数据绑定的方法,而不是基于过程事件的方法。

例如,当用户更改ComboBox中的选择时,基于ComboBox的UI“做东西”应该像这样定义:

ItemsControl

视图模型:

<ComboBox ItemsSource="{Binding MyCollection}"
          SelectedItem="{Binding SelectedItem}"/>
  

现在你有更多的任务,更多的变量,更多的功能   只调用其他函数而不仅仅是一个简单的MyTitlesUI.SelectedItem   处理。

错误。您现在拥有的是{strong} public class ViewModel { public ObservableCollection<MyItems> MyCollection {get;set;} private void _selectedItem; public MyItem SelectedItem { get { return _selectedItem; } set { _selectedItem = value; NotifyPropertyChanged(); DoStuffWhenComboIsChanged(); } } private void DoStuffWhenComboIsChanged() { //... Do stuff here } } 类型的ViewModel中的强类型属性,而不是可怕的投射内容{{ 1}}或类似的东西。

这种方法的另一个优势是你的应用程序逻辑与UI完全分离,因此你可以自由地在UI上做各种疯狂的事情(例如替换ComboBox 3D旋转粉红色大象,如果你想)。

  

为什么不将DBClass引用带到View或类似的?

因为数据库代码不属于用户界面

  

特别是如果你正在进行大量的UI操作

您不在WPF中执行“UI操作”。你做DataBinding这是一种更清洁和可扩展的方法。