MVVM Light Toolkit - RelayCommands, DelegateCommands, and ObservableObjects
-
15-10-2019 - |
سؤال
I just started experimenting with Laurent Bugnion's MVVM Light Toolkit. I think I'm going to really like it, but I have a couple questions.
Before I get to them, let me explain where I'm coming from. I currently use a combination of Josh Smith's MVVM Foundation and another project on Codeplex called MVVM Toolkit. I use ObservableObject
and Messenger
from MVVM Foundation and DelegateCommand
and CommandReference
from MVVM Toolkit.
The only real overlap between MVVM Foundation and MVVM Tookit is that they both have an implementation for ICommand
: MVVM Foundation has RelayCommand
and MVVM Tookit has DelegateCommand
. Of these two, DelegateCommand
appears to be more sophisticated. It employs a CommandManagerHelper
that uses weak references to avoid memory leaks.
With that said, here are my questions:
Why does MVVM Light use
RelayCommand
rather thanDelegateCommand
? Is the use of weak references in anICommand
unnecessary or not recommended for some reason?Why is there no
ObservableObject
in MVVM Light?ObservableObject
is basically just the part ofViewModelBase
that implementsINotifyPropertyChanged
, but it's very convenient to have as a separate class because view-models are not the only objects that need to implementINotifyPropertyChanged
. For example, let's say you have a DataGrid that binds to a list ofPerson
objects. If any of the properties inPerson
can change while the user is viewing the DataGrid,Person
would need to implementINotifyPropertyChanged
. (I realize that ifPerson
is auto-generated using something like LinqToSql, it will probably already implementINotifyPropertyChanged
, but there are cases where I need to make view-specific versions of entity model objects, say, because I need to include a command to support a button column in a DataGrid.)
Thanks.
P.S. Here is the code for DelegateCommand
from the MVVM Toolkit:
https://docs.google.com/document/pub?id=1ApCx5SbCfHi5fBhv8Ki3zA6j34sp2t80LQZdj89v8cU
المحلول
It looks like the issue raised by the first question has been solved in the latest build:
According to The MVVM Light Toolkit Codeplex site (under "Raising the CanExecuteChanged event manually"), the CommandManager
has been eliminated altogether.
As for Observable Object
, I have added an item to the Issue Tracker on the Codeplex Site.
نصائح أخرى
You can also consider Catel. It supports a DataObject (both generic and non-generic) that support exactly what you are looking for (an object implementing INotifyPropertyChanged, IDataErrorInfo, and much more). Then, the ViewModelBase is derived from the very powerful DataObjectBase class, so you can use the DataObjectBase for data objects, and the ViewModelBase for view models.
It also saves you from creating messengers since you can simply use the InterestedIn attribute on a view model to receive change notifications of another view model.
Both of your questions strongly suggest to me that you prefer to use something more than the View Model concept to define business logic.
The DelegateCommand
defines a separate class apart from the View Model. The ObservableObject
is an instance of a separate class apart from the View Model. This is not a rule but personal preference of the moment: the View Model is sufficient for me as a container for business logic, relating to visuals. This may betray my preference for MVVM Light---which I do not find lacking at the moment.
I'm not quite certain about what's going on in the DataGrid example. What I can say is that the DataGrid is not very flexible---however, in WPF, the DataGridTemplateColumn
can declaratively bind a View Model to a View (e.g. a User Control). So perhaps this makes sense:
<DataGridTemplateColumn.CellTemplate>
<DataTemplate DataView="{x:Type m:YourViewModelForButton}">
<v:YourViewWithButton/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>