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
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
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
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
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:
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.