Привязка к команде в сетке данных
Я использую шаблон MV-VM в приложении WPF. Я связываю ViewModel с ContentControl и использую шаблон данных, определенный в ресурсах окна, для визуализации представления (UserControl) для этой ViewModel.
В ViewModel у меня есть коллекция предметов. Я связываю эту коллекцию с сеткой данных, представленной в наборе инструментов WPF. Также в модели представления у меня определена команда RemoveItem, которая принимает аргумент для удаления идентификатора элемента.
Как бы я связался с этой командой в сетке данных? Контекст данных сетки - это то собрание, что-то вроде:
<Button Command="{Binding Path=RemoveCommand}" CommandParameter="{Binding Path=id}">X</Button>
не работает - не может найти команду Я думаю, что мне нужно сделать привязку RelativeSource, но как это будет выглядеть? Будет ли тип Ancestor UserControl или ContentControl? Где моя ViewModel находится как DataContext?
Или я далеко отсюда?
2 ответа
Да, тебе просто нужно подняться на один уровень. Я бы попробовал связать с 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
подход.
Мне нравится определять 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>
...
Обратите внимание, что в этом случае параметр командной строки является целым объектом данных строки. Иногда лучше, чем
CommandParameter="{Binding Id}"
потому что вам не нужно снова искать данные.