所以我正在开发一个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();
}
}
答案 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这是一种更清洁和可扩展的方法。