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 in the 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?
The command is the action to be executed. The command source is the object which invokes the command. The command target is the object that the command is being executed on. The command binding is the object which maps the command logic to the command.
A Grid is a control for laying out other controls on the form (or page). A DataGrid is a control for displaying tabular data as read from a database for example.
The WPF Data Grid (GridControl) is a data-aware control designed to display and edit data in different layouts: tabular, treelike, and card. The GridControl allows users to manage large amounts of data (sort, group, filter, and so on).
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With