Suppose I have a view implemented as a DataTempate inside a resource Dictionary. And I have a corresponding ViewModel. Binding Commands are easy. But what if my View contains a control such as a ListBox, and I need to Publish an application wide event (Using Prism's Event Aggreagtor) based on the Item being Changed on the List.
if ListBox supports a command I could just bind it to a command in the ViewModel and publish the event. But Listbox doesn't allow such an option. How do I bridge this?
EDIT: Many great answers.
Take a look at this link http://blogs.microsoft.co.il/blogs/tomershamam/archive/2009/04/14/wpf-commands-everywhere.aspx
Thanks
Ariel
Well, nobody answered. So I've gave up and moved the implementation of the View outside the Dictionary into a regular UserControl, I've injected him a reference to the ViewModel.
Now when the ListBox fire the Event it's calls the ViewModel and from there everything is possible again.
Ariel
One option is to extend the control in question and add support for the particular command you require. For example, I've modified ListView before to support the
ItemActivated
event and related command.I have been writing behaviors (attached properties) to do this, and there are still cases where I need them.
For the usual case however, simply binding an event to a command, you can do everything in Xaml if you have Blend SDK 4 installed. Note that you will have to add a reference to System.Windows.Interactivity.dll, and to redistribute this assembly.
This example is invoking an ICommand DragEnterCommand on the ViewModel when the DragEnter event of the Grid is fired:
Extend the control to support ICommandSource and decide which action should trigger the command.
I did this with Combo Box and used OnSelectionChanged as the trigger for the command. First I will show in XAML how I bind the command to the extended Control ComboBox which I called CommandComboBox, then I will show the code for CommandComboBox that adds the support for the ICommandSource to ComboBox.
1) Using CommandComboBox in your XAML code:
In your XAML namespace declarations include
Use the CommandComboBox in place of ComboBox and bind the command to it like so: Note that in this example I have a defined a command called SetLanguageCommand im my ViewModel and I am passing the selected value for this ComboBox as the parameter to the command.
2) The code for CommandComboBox
The code for the file CommandComboBox.cs is included below. I added this file to a Class Library called WpfCommandControlsLibrary and made it a separate project so I could easily add any extend commands to whatever solution needed to use them and so I could easily add additional WPF Controls and extend them to support the ICommandSource inteface.
A great solution to this type of problem comes from the usage of Attached Properties. Marlon Grech has taken the usage of Attached Properties to the next level by creating Attached Command Behaviors. Using these it is possible to bind any Command existing in a ViewModel to any Event existing in the view.
This is something I use a lot to deal with similar issues with ListBoxes, where I want them to open, or edit or do some action on a double click.
In this example I'm using an older version of Attached Command Behaviors, but the effect is the same. I have a style that is used for ListBoxItems which I am explicitly keying to. However, it would be easy enough to create a application or window wide style applying to all ListBoxItems that sets the commands at a much higher level. Then, whenever the event for the ListBoxItem attached to the CommandBehavior.Event property would fire, it instead fires off the attached Command.
Instead of trying to bind a command to when the item changes, I looked at the problem another way.
If you bind the selected item of the ListBox to a property in the ViewModel, then when that property is changed you can publish the event. That way the ViewModel remains the source of the event and it is triggered by the item changing, which is what you want.
...