Multiple ViewModels associated with a single view
I have a View that displays a DataGrid
which is bound to an ObservableCollection
in the ViewModel. For the sake of discussion, let's say we have a Team
View containing a Team DataGrid
, in which each row represents a Player
.
My question is about what data type I should use to represent the players in my Team
collecti开发者_开发问答on. Is it a good idea for the items in the collection to be ViewModels themselves? In this case, my Team
View would be associated with a single Team
ViewModel as well as any number of Player
ViewModels (in the Team collection).
Does having multiple ViewModels associated with a single View violate any design guidelines for MVVM , and is there a preferred way of implementing this scenario?
Thanks!
No that is fine; each object should be a ViewModel in its own right. It makes for cleaner code, nicer interactions, and remember, if it works well then it's correct (even if it violates guidelines).
I would do it exactly the way you are prescribing. I'd bind my grid to a Team
, which would have an ObservableCollection<Player>
, where Player
is another ViewModel-type class. Each row item would get the Player
as its DataContext
and so you're still binding to ViewModel properties as you'd expect: and Player
can still have public
properties for ICommand
s (likely RelayCommands) for manipulation!
Hope that helps!
Far from violating guidelines, I think this is recommendated design. At least in my projects you will see this pattern repeatedly.
This pattern comes in particularly useful in conjunction with DataTemplates. For example you could define a DataTemplate in your Application.Resources for your PlayerViewModel like so:
<DataTemplate DataType="viewModels:PlayerViewModel">
<StackPanel Orientation="Vertical">
<Image Source="/Images/Player.png"/>
<TextBlock Text="{Binding Name}"/>
</StackPanel>
</DataTemplate>
And then if you wanted to display a list of players you simply bind a ListBox etc to your TeamViewModel.Players ObservableCollection and you automatically get the above DataTemplate displayed for each player:
<ListBox ItemsSource="{Binding Players}"/>
I agree with both of the other answers (the ones by Kieren and Groky) but feel they fail to mention a very important consideration in this decision.
You should only create a view model if there is something view-specific about what you are doing. If all you are doing is binding to data and invoking commands which naturally belong on your model, there is no reason to create a view model.
For example, suppose:
- Your Player object has a Name property, a Rank property, a Promote() method, and a Delete() method.
- Your view is a simple one that allows you to edit the Name and Rank of any player, and also has buttons to promote and delete players.
In this case adding a view model between your view and your model is pointless. Such a view can bind directly to the model:
- Bind TextBox.Text to the Name property
- Bind Slider.Value to the Rank property
- Bind the Promote button to the Promote() method
- Bind the Delete button to the Delete() method
Note that instead of binding the Delete button to the Delete() method you may want to set its Command to ApplicationCommands.Delete and use a CommandBinding to invoke the Delete() method.
My point here is that in most cases if your models are well-designed there will be no need to insert a view model object. A view model is only really necessary when view-specific state needs to be tracked (such as "current Player"), conversions are too complex to be handled by simple binding, or you need commands that affect several different model objects and/or view model properties at the same time.
In my experience, if the model is correctly designed only about 50% or so of all views actually need a view model, and in the case of items in a list this is more like 20%.
An example of a time when you might use a view model for an item in a list is when you need to keep a separate "selected" flag that is part of your view but not of your model, and the basic functionality in ListBox is not enough.
By CLEAN COD SOLID principles, it is nice to associate one view model to one view. Separation of concerns should be separated for each view and it's much easier to maintain the codebase in the future. You can do it but it's not recommended.
精彩评论