Friday, April 8, 2011

Binding to a command in a datagrid

I am using the M-V-VM pattern in a WPF app. I am binding a ViewModel to a COntentControl and using a data template defined int eh window resources to render the view (a UserControl) for that ViewModel.

In the ViewModel, I have a collection of items. I'm binding that collection to the data grid provided in the WPF toolkit. Also in the view model, I have a RemoveITem command defined which takes an argument for the item ID to remove.

How would I bind to that command in the data grid? The grid's data context is that collection, so something like:

<Button Command="{Binding Path=RemoveCommand}" CommandParameter="{Binding Path=id}">X</Button>

doesn't work - it can't find the command. I think I need to do RelativeSource binding, but what would that look like? Would the Ancestor type be USerControl, or the ContentControl? Where is my ViewModel residing as the DataContext?

Or am I way off here?

From stackoverflow
  • Yeah, you just need to get one level up. I'd try a binding with ElementName first and resort to RelativeSource only if necessary. For example, I'd prefer this:

    <DataGrid x:Name="_grid">
        ...
            <Button Command="{Binding DataContext.RemoveItem, ElementName=_grid}"/>
        ...
    </DataGrid>
    

    That said, the XAML compiler can get its knickers in a knot when it comes to element names and scoping in controls, so you may need to resort to a RelativeSource:

    <DataGrid x:Name="_grid">
        ...
            <Button Command="{Binding DataContext.RemoveItem, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGrid}}}"/>
        ...
    </DataGrid>
    

    You only need to search up until the data context will be your view model. You could search for a UserControl if you wanted to - not sure it really matters. Both are pretty fragile bindings, which is why I prefer the ElementName approach.

    HTH, Kent

    Adam Barney : Awesome. Thanks, Kent!
    Kent Boogaart : Welcome. Another way to do this is to expose a collection of child view models rather than a collection of data items. Then, those child view models can have a property that exposes the command, saving you from introducing fragile bindings like these.
    Jonathan Allen : Thank you, that solved my problem.

0 comments:

Post a Comment