Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WPF MVVM - Command binding inside of an ItemsControl

Tags:

.net

mvvm

wpf

I'm currently converting a small WPF project to MVVM. I have a List<CustomObject> in the ViewModel of the main window that my ItemsControl binds to and uses a DataTemplate to build the UI of each element. My old code used an event handler inside the DataTemplate to handle a click event. I want to use some kind of command binding to eliminate my code-behind event handlers, but the DataContext of the items in my ItemsControl is the model object so I can't currently bind to an ICommand from the ViewModel.

So, I guess there are a couple of ways to attack this and I'm not sure which would be the most "MVVM" way of doing it. Do I bind the ItemsControl.ItemsSource to a collection of a new ViewModel class that represents each item? Or do I use UserControls instead of a DataTemplate and then I can bind each UserControl to it's own instance of a ViewModel that represents it? Or is there some kind of binding expression I can use to refer back to the DataContext of the window to have access to bind to the ViewModel (as I type this, it just sounds bad so I'm assuming a big "NO" to this idea)?

Also, what I want to bind my command to is the LeftMouseButtonUp event of a Grid control. There's no "Command" for a Grid, so I was attempting to use InputBindings. I could use a static command (such as one of the built in ApplicationCommands), but I could not use a binding expression to bind to an ICommand instance that is a property of the ViewModel because MouseBinding.Command is not a DependencyProperty.

I'm pretty confused on the subject of event handling in MVVM, so any and all info is appreciated.

like image 251
Rich Avatar asked Jun 26 '09 21:06

Rich


1 Answers

Do I bind the ItemsControl.ItemsSource to a collection of a new ViewModel class that represents each item?

Whether you create a CustomObjectViewModel to host the command or place the command within the same ViewModel that has the list really depends on the function of the action occuring. Is it something that belongs with the CustomObject, or is it something that belongs with your current ViewModel?

Or is there some kind of binding expression I can use to refer back to the DataContext of the window to have access to bind to the ViewModel (as I type this, it just sounds bad so I'm assuming a big "NO" to this idea)?

This isn't as bad as it sounds. You don't really need the DataContext of the Window, just the DataContext from before it switched over to the individual items. So if your command was on the same ViewModel that hosts the List of CustomObjects, you could bind to it from within one of the CustomObject's DataTemplate using either of these methods:

{Binding ElementName=uiCustomObjectsItemsControl, Path=DataContext.MyCommand}
{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ItemsControl}}, Path=DataContext.MyCommand}

Also, what I want to bind my command to is the LeftMouseButtonUp event of a Grid control. There's no "Command" for a Grid, so I was attempting to use InputBindings.

For this, I would use something like Attached Command Behaviors which will let you attach a ICommand to any event.

like image 103
rmoore Avatar answered Oct 21 '22 16:10

rmoore