I'm trying to learn the MVVM pattern. The main problem I'm having is learning where I should be declaring, creating and binding command objects.
2 examples:
I have a main form that acts like a switch board or main menu. Selct button 1 and View 1 is displayed, Select button 2 and view 2 is displayed. Great. Now I want to go back to the main form so I need a button on View 1 (and view 2) called "Main Menu". Where should I define the command and command handlers so that I can bind to the "ShowMainMenu" command? I could create them in the View2ViewModel but then I don't have access to show the Main View? Or, I could create thim in the MainView model but then How do I bind to them in the child view model (I'm using the RelayCommand obejct as per the mvvm recommendation and they don't bubble up to the parent.)
I have two user controls visible on a single Main Window view let's call them MainView, UC1 and UC2. each of these has ViewModel MainViewModel, UC1ViewModel, UC2View Model. I have a button on UC1 called "AddItem". It should add an item in a list on UC2. What is the currect way to set up an "AddItemCommand" and bind to it. Should the Command be in MainViewModel, Uc1ViewModel or UC2ViewModel? And How shoud I bind to it.
Thanks for your help.
1) You can inherit View1Model and View2Model from one base ViewModel and define ShowMainMenu there.
or (it's my approach)
Create RootView with ContentPresenter which will show all of your views. Create RootVeiwModel with property ViewContent. Bind Content propertty of ContetnPresenter to ViewContent property of RootViewModel. You can use object
as type of ViewContent, but I advise you to define the interface that is supported by MainVView1Model, View1Model and View2Model. Changing of ViewContent must raise ProprtyChangedEvent.
Define ShowMainViewCommand in RootViewModel which will just change ViewContent to MainViewModel (and it will show as MainView). Then bind Command property of Button in View1 and View2 to that command, for exmple that way:
{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type RootView}},
Path=DataContext.ShowMainViwe}
There is some code to explain what I'm trying to say:
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) Add reference to MainViewModel to UC1ViewModel and UC2ViewModel - thats the way to influence other controls. MainViwModel must contain properties that contains UC1ViewModel and UC2ViewModel Items of second user control must be contained in ObservableCollection.
I just show you how it works by the code:
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;
}
}
...
}
The MainModel could have a property for each UCxViewModel or, easier, a list of ViewModels. The "Show" command would create a corresponding UVxViewModel, subscribe to a "OnClose" event published by the UVxViewModel, and add it to the list. The MainView has a control (Tab Control for example) bound to this list and DataTemplates defining the Views to be used for each UCxViewModel. When the UVxViewModel fires its OnClose event, the MainModel removes it from the list, causing the corresponding view to "close".
For the "Add Item" part, the ViewModels should share the same list of items (the Model). The UC2ViewModel can then add an item and the UC1View would get updated (provided the list implements INotifyCollectionChanged).
I found this explanation very helpful in understanding MVVM.
来源:https://stackoverflow.com/questions/1852084/mvvm-command-binding