I am looking for advice on handling states in a WPF MVVM environment.
As an example, assume we have
- A TreeView (or some other ItemsControl) with some items and
- a button that is enabled when an item is selected.
My ViewModel contains a property SelectedItem
that is bound to the SelectedItem
of the TreeView.
When the Button is clicked, we change to "special state": the current SelectedItem
is stored somewhere for later reference (let's call the storing variable FirstSelectedItem
). Then the Selection is cleared, the Button is disabled and the user is supposed to select an item again (can be any item, even the same one). So we get some entry in SelectedItem
. Then the data of the item stored in FirstSelectedItem
is changed depending on SelectedItem
(change some internal properties that are not visible in the view). After this is done, SelectedItem
is restored to contain FirstSelectedItem
, the Button is enabled and the view is in "normal state" again.
I would like to know how you approach such problems in WPF. For me it is important to use the MVVM pattern and use codebehind only to redirect stuff to the ViewModel, and that it is possible to give every UI element a different look and behaviour depending on the current state. In a more complicated example, it might be that some controls become disabled or show up or execute another command than usual when a certain state is current.
For the looks, I think a way would be to have some property State
in the ViewModel. The UI elements can then somehow make their looks dependent on that state (although I don't know how, but I'm sure it's possible).
For the behaviour, I have no idea. As far as I know, a Button can bind to one Command, and only one. Or can the binding be changed depending on State
?
Best Answer
If I understand what you are saying, you need some UI cue to denote when the
State
property changes. There are many ways to do it in pure MVVM.You could use a ValueConverter to convert the value of the state to a System.Windows.Visibility value have that bound to the visibility of certain elements in order to facilitate visibility changes based on the
State
property. You could do the same with a converter to convert state to a boolean in order to facilitateIsEnabled
orIsReadOnly
changes too.Then, if you wanted the button command to change depending on the state you could change the binding and raise a
PropertyChanged
on the command for the button. Or just change the underlying method if you are using something like a RelayCommand seen here. Or you could just have a command that executes some routine that is affected by theState
property. Or maybe pass in the state as a command parameter.You could also use DataTemplates and bind a DataTemplate to the
State
property.Facilitating a state change, depending on what that means, could be business logic, and that should probably not go in the ViewModel (Unless, like Rachel said, it is a very small app with limited need for abstraction). However, what you are attempting to do with the UI can be done with bindings and ViewModel property changes/notifications. There are 1,000 ways to skin a cat, you just need to find the one that best suits you.