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 доступно.