Подтвердить что ты не робот

Привязка к команде в 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?

Или я здесь отсюда?

4b9b3361

Ответ 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}"  

потому что вам не нужно снова искать данные.