Up until this point, we’ve relied exclusively on data-binding for the link between our view-models and our views. While data-binding handles a lot of scenarios well, it doesn’t support buttons, menu items and so on.
We could take an approach based on experience with WinForms, using event handlers to respond to button clicks, and so on.
Fortunately, WPF offers a much better approach - one that allows for better separation of concerns and testability: command-binding.
Hooking up a command for the “Add” button on our VocabularyBrowserView
will require three steps: Configuring a command on the button, providing an implementation of the command on our view model, and wiring the two together.
Configuring the command
Our Add
button has a Command
property that we can use to associate a selected command with the button.
The WPF framework includes many predefined commands but none of them are quite right for our situation. The closest are the New
and Save
commands from ApplicationCommands, but we want to keep those for whole vocabulary lists, not individual words. (If you’re curious, you might also want to check out the predefined commands on
ComponentCommands,
EditingCommands,
MediaCommands, and
NavigationCommands).
Instead, we’ll define our own.
Each property has a unique identity made up of the provided name and the declaring class. This allows similar properties declared on different classes to be told apart.
We now add the New
command to our button:
Implementing the command
On our VocabularyBrowserViewModel
, we add a method for the command to trigger:
With all our application logic centred in the model, our view model command implementations should all remain this straightforward.
Now we wrap that method using a RoutedCommandSink
, converting the method (which is easy to test) into a command that can be linked to our button.
Notice the naming convention we’re using here - the property is named for the method, with the suffix Command
included; we’ll start enforcing the convention in a later post.
Wiring up the command
We now have a command configured on the button and an implementation of that command available on our view-model.
To wire them together, we need to add a CommandBinding
to the CommandBindings
collection of our view.
We could manually create each CommandBinding
and add it to the collection ourselves.
But since every view will need the same wiring to occur, we’ll instead add the necessary logic to ViewFactory
. This will ensure that all our commands are wired up automatically for every view.
After creating the view and assigning its DataContext
, we add any extra command bindings required:
The CreateCommandBindings()
method looks for any properties with names ending Command
and uses those values.
We iterate over all of the properties on the model, looking for those with a name ending in Command
, and from each of those, creating a command binding.
Running the application, you can now press the Add button and bring up a new screen.
Next time, we’ll put a few more commands to work.
Comments
blog comments powered by Disqus