我正在尝试学习MVVM模式。我遇到的主要问题是学习我应该声明的位置,创建和绑定命令对象。
2个例子:
我有一个主要表单,就像一个开关板或主菜单。显示选择按钮1和视图1,选择按钮2,显示视图2。大。现在我想回到主窗体,所以我需要一个名为“主菜单”的视图1(和视图2)上的按钮。我应该在哪里定义命令和命令处理程序,以便我可以绑定到“ShowMainMenu”命令?我可以在View2ViewModel中创建它们但是我没有权限显示主视图?或者,我可以在MainView模型中创建thim但是然后如何在子视图模型中绑定它们(我根据mvvm建议使用RelayCommand obejct并且它们不会冒泡到父级。)
我在一个主窗口视图中可以看到两个用户控件,我们称之为MainView,UC1和UC2。每个都有ViewModel MainViewModel,UC1ViewModel,UC2View Model。我在UC1上有一个名为“AddItem”的按钮。它应该在UC2的列表中添加一个项目。 设置“AddItemCommand”并绑定到它的当前方法是什么。 Command应该在MainViewModel,Uc1ViewModel还是UC2ViewModel?我怎么会和它结合起来。
感谢您的帮助。
答案 0 :(得分:3)
1)您可以从一个基本ViewModel继承View1Model和View2Model,并在那里定义ShowMainMenu。
或(这是我的方法)
使用ContentPresenter创建RootView,它将显示您的所有视图。使用ViewContent属性创建RootVeiwModel。将ContetnPresenter的内容属性绑定到RootViewModel的ViewContent属性。您可以使用object
作为ViewContent的类型,但我建议您定义MainVView1Model,View1Model和View2Model支持的接口。更改ViewContent必须引发ProprtyChangedEvent。
在RootViewModel中定义ShowMainViewCommand,它只会将ViewContent更改为MainViewModel(它将显示为MainView)。然后将View1和View2中Button的Command属性绑定到该命令,例如:
{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type RootView}},
Path=DataContext.ShowMainViwe}
有一些代码可以解释我想说的内容:
RootView.xaml
...
<ContentPresenter Content={Binding ViewContent} />
...
RootViewModel.ca
class RootViewModel : INotifyPropertyCahnged
{
...
private object _ViewContent;
public object ViewContent
{
get {return _ViewContent;}
set
{
_ViewContent = value;
if (PropertyChanged != null)
{
PropertyChanged ("ViewContent");
}
}
}
private RelayCommand _ShowMainView;
public ICommand ShowMainView
{
get
{
if (_ShowMainView == null)
{
_ShowMainView = new RelayCommand(x => ViewContent = new MainViewModel());
}
return _ShowMainView;
}
}
...
}
2)将对MainViewModel的引用添加到UC1ViewModel和UC2ViewModel - 这就是影响其他控件的方式。 MainViwModel必须包含包含UC1ViewModel和UC2ViewModel的属性第二个用户控件的项必须包含在ObservableCollection中。
我只是通过代码向您展示它是如何工作的:
class UC1ViewModel : INotifyPropertyChanged
{
...
private MainViewModel _Parent;
public UC1ViewModel(MainViewModel parent)
{
_Panert = parent;
}
private RelayCommand _AddItemToUC2;
public ICommand AddItemToUC2
{
get
{
if (_AddItemToUC2 = null)
{
// UC2Content is UC2ViewModel
// Items is ObservableCollection
_AddItemToUC2 = new RelayCommand(x => _Parent.UC2Content.Items.Add(...));
}
return AddItemToUC2;
}
}
...
}
答案 1 :(得分:2)
MainModel可以为每个UCxViewModel提供一个属性,或者更简单的是ViewModel列表。 “Show”命令将创建相应的UVxViewModel,订阅由UVxViewModel发布的“OnClose”事件,并将其添加到列表中。 MainView具有绑定到此列表的控件(例如Tab控件)和定义要用于每个UCxViewModel的视图的DataTemplates。 当UVxViewModel触发其OnClose事件时,MainModel将其从列表中删除,从而导致相应的视图“关闭”。
对于“添加项目”部分,ViewModel应共享相同的项目列表(模型)。然后UC2ViewModel可以添加一个项目,UC1View会更新(如果列表实现了INotifyCollectionChanged)。
我发现this explanation对理解MVVM很有帮助。