CommandParameters в ContextMenu в WPF
У меня есть сценарий, где у меня есть элемент управления TreeView WPF, который имеет HierarchicalDataTemplate
для своих элементов. Теперь внутри HierarchicalDataTemplate
у меня есть Label
, а Label
имеет ContextMenu
с элементом меню для Delete
. Элемент меню Delete привязан к команде под названием DeleteCommand
, которая является частью класса, который был установлен как DataType
для HierarchicalDataTemplate
.
Теперь я хочу передать элемент управления TreeView
в CommandParameters
элемента меню ContextMenu Delete
DeleteCommand
, чтобы я мог обрабатывать выбор TreeViewItems при удалении текущего выбранного элемента.
Но если я привяжу CommandParameters
как {Binding ElementName=TreeViewName}
или что-то в этом роде, оно всегда равно null, если связанный элемент не является свойством в DataContext
.
Может ли кто-нибудь помочь мне с решением, потому что я думаю, что я пробовал все возможные вещи, такие как RelativeSource и AncestorType и т.д., но всегда всегда null. Для меня это похоже на ограничение или ошибку в структуре.
Ответы
Ответ 1
Проблема заключается в том, что ContextMenu находится в корне своего собственного визуального дерева, поэтому любые привязки RelativeSource.FindAncestor не будут проходить через ContextMenu.
Одним из решений является использование свойства PlacementTarget для установки двухэтапного связывания с вашей меткой:
<Label Tag="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={
x:Type TreeView}}}">
<Label.ContextMenu>
<ContextMenu>
<MenuItem Header="Delete" Command="{x:Static local:Commands.DeleteCommand}"
CommandParameter="{Binding PlacementTarget.Tag, RelativeSource={
RelativeSource FindAncestor, AncestorType={x:Type ContextMenu}}}"/>
</ContextMenu>
</Label.ContextMenu>
</Label>
Тем не менее, это довольно взломанно. Вам лучше установить свойство CommandTarget вашего MenuItem в ContextMenu PlacementTarget и иметь обработчик команд в вашем TreeView. Это означает, что вам не придется проходить TreeView вокруг.
Ответ 2
<ContextMenu>
<MenuItem Header="Edit Item"
Command="{Binding EditItemCommand, Mode=OneWay}"
CommandParameter="{Binding Path=UIElement.(views:DataGridView.SelectedItems), RelativeSource={RelativeSource AncestorType={x:Type ContextMenu}}}" />
<ContextMenu>
Ответ 3
<MenuItem Header="..."
Command="{Binding Path=...}"
CommandParameter="{Binding Path=PlacementTarget, RelativeSource={RelativeSource Mode=FindAncestor, AncestorLevel=1, AncestorType={x:Type ContextMenu}}}">
</MenuItem>
ContextMenu.PlacementTarget, это ярлык, где размещается элемент меню. Из Lavel его родительское Treeview доступно.
Ответ 4
Взгляните на задачу привязки WPF CommandParameter. Возможно, он может дать некоторые указания относительно того, что происходит.