Привязка к команде в datagrid
Я использую шаблон M-V-VM в приложении WPF. Я привязываю ViewModel к ContentControl и использую шаблон данных, определенный в ресурсах окна, для визуализации представления (UserControl) для этой ViewModel.
В ViewModel у меня есть набор элементов. Я привязываю эту коллекцию к сетке данных, представленной в наборе инструментов WPF. Также в модели представления у меня есть команда RemoveItem, которая принимает аргумент для удаления идентификатора элемента.
Как мне привязать эту команду в сетке данных? Контекст данных сетки - это коллекция, поэтому что-то вроде:
<Button Command="{Binding Path=RemoveCommand}" CommandParameter="{Binding Path=id}">X</Button>
не работает - он не может найти команду. Я думаю, мне нужно сделать привязку RelativeSource, но как это будет выглядеть? Будет ли тип предка быть UserControl или ContentControl? Где мой объект ViewModel, находящийся в качестве DataContext?
Или я здесь отсюда?
Ответы
Ответ 1
Да, вам просто нужно подняться на один уровень. Сначала я попробую привязку с ElementName
и прибегните к RelativeSource
только при необходимости. Например, я бы предпочел это:
<DataGrid x:Name="_grid">
...
<Button Command="{Binding DataContext.RemoveItem, ElementName=_grid}"/>
...
</DataGrid>
Тем не менее, компилятор XAML может получить свои трусики в узле, когда речь заходит об именах элементов и оглавлении элементов управления, поэтому вам может понадобиться обратиться к RelativeSource
:
<DataGrid x:Name="_grid">
...
<Button Command="{Binding DataContext.RemoveItem,
RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type DataGrid}}
}"/>
...
</DataGrid>
Вам нужно только выполнить поиск до тех пор, пока контекст данных не станет вашей моделью просмотра. Вы могли бы искать UserControl
, если хотите - не уверены, что это действительно важно. Оба являются довольно хрупкими привязками, поэтому я предпочитаю подход ElementName
.
Ответ 2
Мне нравится определять viewmodel в datacontext элемента управления с именем ViewModel. Связывание легче писать с помощью ElementName
...
<UserControl.DataContext>
<local:UserControlViewModel x:Name="ViewModel"/>
</UserControl.DataContext>
...
...
<DataGridTemplateColumn Width="30">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Button Command="{Binding RemoveCommand, ElementName=ViewModel}"
CommandParameter="{Binding}">Remove</Button>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
...
Обратите внимание, что в этом случае Command Parameter является целым объектом данных строки. Когда-нибудь лучше, чем
CommandParameter="{Binding Id}"
потому что вам не нужно снова искать данные.