tags:

views:

5747

answers:

3

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.

+3  A: 

Josh Smith wrote an excellent article in MSDN here where he talks about command binding.

In your case it boils down to this:

  • You won't eliminate ALL of your code-behind, but it will probably look different
  • Your CustomObjects will probably have to have VM shim classes, or be VMs themselves to take advantage of the RelayCommand architecture that he describes.

HTH.

micahtan
+5  A: 

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.

rmoore
A: 

doesn't seem to work: {Binding ElementName=uiCustomObjectsItemsControl, Path=DataContext.MyCommand}

isn't in silverlight: {Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ItemsControl}}, Path=DataContext.MyCommand}

anonymous