问题
I am writing this major memory trainer using the MVVM pattern by animating labels containing 2 digit numbers across the screen and asking the user to quickly type in the corresponding mnemonic for each number. It is entirely up to the View how the animation is done so there will be some code behind for this. When the correct mnemonic is typed into the UI or when the number disappears off the screen Commands will be executed from the View to relay that this has happened.
In the ViewModel I want to periodically fire off new numbers with which the View animates (as it pleases).
What's the best way of achieving this? I can have an ObservableCollection<> in the ViewModel but I want to do more than simply bind to it, I will need to execute a method in the code behind when numbers are added and removed.
Is it in accordance with MVVM to use simple .NET events in the ViewModel and subscribe to them with: DataContext.NumberAdded += new NumberAddedEventHandler(....) or is there another way I should be doing it?
回答1:
A View is meant to be a user-friendly reflection of the ViewModel. If you have view-specific logic to run (such as triggering an animation), there's no reason not to use code-behind to run it.
Providing you keep your UI and data layers separate, you're fine.
That said, providing a NumberAdded
event from the ViewModel doesn't really make sense to me if you're only using it from the View layer. That's mixing up your layers.
Instead I would simply use the regular CollectionChanged
((MyViewModel)this.DataContext).Numbers.CollectionChanged +=
new CollectionChangedEventHandler(....);
Depending on how your collection is bound to the UI, you may also be able to use a UI event, or possibly triggers instead.
I thought elements with an ItemsSource
raised an event when an item got added or removed, or you could simply cast the ItemsSource
property into a collection and hook up to the CollectionChanged
event there without needing to reference MyViewModel
void SomeItemsControl_DataContextChanged(...)
{
var collection = (SomeItemsControl.ItemsSource as ObservableCollection);
if (collection != null)
collection.CollectionChanged += new CollectionChangedEventHandler(....);
}
回答2:
Why do you reckon binding to it is bad?
I would probably bind to the ObservableCollection<T>
from the View.
Create a DependencyProperty
of ObservableCollection<T>
in the View and on the PropertyChanged Callback subscribe to the OnCollectionChanged
event which can then process the animation accordingly based on the contents of the ObservableCollection<T>
in the View.
This way the VM just updates the collection with these numbers that you mention and the View is hooked up to action whenever the collection changes in the manner it desires fit
回答3:
Use Attached Behaviours to bind your viewmodel properties to any custom behaviour you need.
来源:https://stackoverflow.com/questions/16299955/is-it-ok-to-subscribe-to-the-viewmodels-net-events-from-the-view-in-mvvm