MVVM ViewModel scope
My View is pretty complicated. It will have some charts, grids, combo boxes, etc. Some of these things will bind to different data. My understanding is that each view has a single view model associated with it. So in this case, my view model will end up being pretty big since it needs to have the data that each of the components in the view will bind to. Is that just the way it has to be if a view is complex?
Also, I'm used to adding event handlers to my controls and just handling events that way. In the MVVM way, how should I h开发者_如何学JAVAandle events? For example, I'm stuck on how I can properly handle a chart's mouse move events or a grid's selection changed event in the MVVM way.
I partly agree with both @Rich and @Elad Katz. In our applications, we use a MainViewModel that has properties that represents sub-ViewModels. Such as
public class MainViewMod
{
public SomeViewModel ContentViewModel
{
get;
set;
}
public StatusBarViewModel StatusBarViewModel
{
get;
set;
}
}
MainView gets it's DataContext from MainView. Say MainView is a window, and it has a <ContentControl Content="{Binding ContentViewModel}" />
and <ContentControl Content="{Binding StatusBarViewModel}" />
.
The different ContentControls "live" somewhere inside the visual tree of MainView.
The different ViewModel's don't need to know about each other. As long as you have a loose relationship between the viewModels, I don't see a problem with sub-viewmodels. My rule of thumb is that StatusViewModel can access MainViewModel. In some scenarios, StatusViewModel can access ContentViewModel, but only through MainViewModel, but keep that at a minimum. But keep in mind what @Elad said about not having them depend too much on each other.
When it comes to events, there are not many scenarios I have needed to access evens directly in the ViewModel. Say you have a view that has a listView, and you need to either get or set the selected item. In that case, I would add a property to the ViewModel, i.e. SelectedItem, and bind that property to the listviews's SelectedItem. That way, youg could access the selected item from the viewmodel.
Keep in mind that there is no problem having code-behind for the view. In some situations you have to use code-behind. I would, however, recommend against subscribing to the events in code-behind as then they are hard to find (say one out of 20 views has code-behind, it is not natural to look into the codebehind for any view to find any code there to understand what is happening). If you use events for an element, either use command bindings as mentioned in other answers, or subscribe to the event in XAML. In several situations I prefer using attached behavior if I need access to the viewmodel.
Usually if a ViewModel gets too large it's a good sign that your view separation is not good enough, and that you should have used more than one View&ViewModel for the situation.
I actually advise against what @Rich said about the child viewModels. I've seen that usage plenty of times and it's rather popular, but I think that although it keeps the idea behind MVVM, it isn't helpful in the larger scheme of things, i.e. the ViewModels become dependent of one another. ViewModels should be as separated as possible from one another, as if being the only thing in the application.
Events are typically handled by binding to an ICommand. Since there is usually only a limited set of properties on a control that can bind to an ICommand, there are frameworks that allow you to attach actions dynamically to commands where you would otherwise use an event. I've used AttachedCommandBehavior and it worked great. If this doesn't work for you, I'm sure there are others.
As far as the issue of an overgrown ViewModel, you can quite often have child ViewModels for views within another view. For example, if you have list controls, they can often be bound to collections of a more light weight ViewModel bound to a DataTemplate defined externally. This usually gives you a good separation when your code files have grown out of control.
Creating a viewModel that will centralize other vm's is an option that for my opinion is an exception. MVVM can work with Mediator design pattern, it is a behavioural pattern that commits to transfer data and between two objects (view and viewModel) and can execute methods on their behalf accordingly to wanted logic. Mediator pattern can keep viewModel concern while dealing with view response to it's bind/observe.
精彩评论