WPF treeview contextmenu命令参数

时间:2013-10-02 09:17:35

标签: wpf treeview contextmenu commandparameter

TreeView HierarchicalDataTemplate。在TreeView我有ContextMenu

<TreeView Name="_packageTreeView" ItemsSource="{Binding PackageExtendedList}" Behaviors:TreeViewInPlaceEditBehavior.IsEditable="True">
    <TreeView.ContextMenu>
        <ContextMenu StaysOpen="true">
            <MenuItem Header="Добавить пакет" Height="20" Command="{Binding AddPackageCommand}" 
                CommandParameter="{Binding ElementName=_packageTreeView, Path=SelectedItem}">
                    <MenuItem.Icon>
                        <Image Source="/Resources/ManualAdd.png" Width="15" Height="15"></Image>
                    </MenuItem.Icon>
            </MenuItem>
        </ContextMenu>
   </TreeView.ContextMenu>
   <TreeView.ItemTemplate>
       <HierarchicalDataTemplate ItemsSource="{Binding Childs}">bla bla bla</HierarchicalDataTemplate>
   </TreeView.ItemTemplate>
</TreeView>

如您所见,我将Command绑定到菜单项。通常在ViewModell类中定义AddPackageCommand。调用命令工作正常,但null中始终有CommandParameter。我发现了一些类似于我的问题,但我不明白解决方案。例如:

CommandParameters in ContextMenu in WPF

无论如何它对我不起作用:(我做错了什么?

更新

这似乎有效,但它完全相同,我不明白为什么CommandParameter不能与TreeView.Name一起使用。

CommandParameter="{Binding PlacementTarget, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ContextMenu}}}"

例如,这样的样本工作正常

<i:EventTrigger EventName="SelectedItemChanged">
    <i:InvokeCommandAction Command="{Binding PackageTreeItemChangeCommand}" CommandParameter="{Binding ElementName=_packageTreeView, Path=SelectedItem}"/>
</i:EventTrigger>

到底是什么......

无论如何,我在TreeView中有CommandParameter个对象,而不是TreeViewItem。我可以从SelectedItem获取TreeView,但如何准确发送TreeViewItem作为CommandParameter

致Sheridan

问题是为什么这不起作用。

CommandParameter="{Binding ElementName=_packageTreeView, Path=SelectedItem}"

这有效

CommandParameter="{Binding PlacementTarget, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ContextMenu}}}"

为什么有时我可以使用直接的TreeView控件名称,有时候我不能。 据我所知,问题是TreeView控件和ContextMenu的DataContext不同,因为ContextMenu有自己的VisualTree,而不是TreeView ViaualTree的一部分。< / p>

不幸的是,这种方法也不起作用,我再次null。我设置了TreeView.Tag,当然。

<ContextMenu DataContext="{Binding PlacementTarget.Tag, RelativeSource={
            RelativeSource Self}}" StaysOpen="true">
    <MenuItem Header="Добавить пакет" Height="20" Command="{Binding AddPackageCommand}" 
                CommandParameter="{Binding ElementName=_packageTreeView, Path=SelectedItem}">
        <MenuItem.Icon>
             <Image Source="/Resources/ManualAdd.png" Width="15" Height="15"></Image>
        </MenuItem.Icon>
    </MenuItem>
</ContextMenu>

这是最简单的方法,但如果我在ViewModel中有SelectedItem属性,则无法将其绑定到CommandParameter,因为我已在ViewModel中使用它。

 <MenuItem Header="Добавить пакет" Height="20" Command="{Binding AddPackageCommand}" 
    CommandParameter="{Binding SelectedItem}">
    <MenuItem.Icon>
        <Image Source="/Resources/ManualAdd.png" Width="15" Height="15"></Image>
    </MenuItem.Icon>
</MenuItem>

1 个答案:

答案 0 :(得分:1)

你告诉我们你已经有了答案......为什么你在同一主题上发布了另一个问题,而不是简单地按照答案中的例子?它不适合您,因为您没有正确复制答案。

在回答示例中,Tag属性设置为应用菜单的TreeView控件,但您尚未执行此操作。

您的下一个问题是您在Tag中再次忽略了此CommandParameter属性...不知何故,您已从正确答案中更改此内容:

CommandParameter="{Binding PlacementTarget.Tag, RelativeSource={RelativeSource 
    FindAncestor, AncestorType={x:Type ContextMenu}}}
在您的问题中

CommandParameter="{Binding PlacementTarget, RelativeSource={RelativeSource 
    FindAncestor, AncestorType={x:Type ContextMenu}}}"

您需要做的就是复制并粘贴它。尽管如此,你可能会有更多的运气:

<TreeView Tag="{Binding DataContext, RelativeSource={RelativeSource Self}}" 
    Name="_packageTreeView" ItemsSource="{Binding PackageExtendedList}" 
    Behaviors:TreeViewInPlaceEditBehavior.IsEditable="True">
    <TreeView.ContextMenu>
        <ContextMenu DataContext="{Binding PlacementTarget.Tag, RelativeSource={
            RelativeSource Self}}" StaysOpen="true">
            <MenuItem Header="Добавить пакет" Height="20" Command="{Binding AddPackageCommand}" 
                CommandParameter="{Binding ElementName=_packageTreeView, Path=SelectedItem}">
                    <MenuItem.Icon>
                        <Image Source="/Resources/ManualAdd.png" Width="15" Height="15"></Image>
                    </MenuItem.Icon>
            </MenuItem>
        </ContextMenu>
   </TreeView.ContextMenu>
   <TreeView.ItemTemplate>
       <HierarchicalDataTemplate ItemsSource="{Binding Childs}">bla bla bla</HierarchicalDataTemplate>
   </TreeView.ItemTemplate>
</TreeView>

查看TreeView.Tag属性...这已设置为自己的DataContext,这意味着现在可以将DataContext TreeView设置为TagContextMenu.DataContext属性对象中。

接下来,查看Tag属性...此设置为PlacementTarget的{​​{1}}属性,ContextMenuTreeview应用于DataContext的控件,或者在这种情况下,ContextMenu

如果您还没有解决,这意味着DataContext的{​​{1}}现在设置为与TreeView的{​​{1}}相同的对象。如果这不是您想要的,因为您的Command位于不同的对象上,那么只需将Binding属性中的Tag路径更改为指向具有{{1}的对象的任何位置是的。

您可以做的最后一件事就是将属性添加到绑定到Command属性的视图模型/代码后面:

TreeView.SelectedItem

然后,您只需为<TreeView SelectedItem="{Binding SelectedItem}"... />

引用此属性即可
CommandParameter

本课程的最后一部分假定您已将视图模型/代码设置为<MenuItem Header="Добавить пакет" Height="20" Command="{Binding AddPackageCommand}" CommandParameter="{Binding SelectedItem}"> <MenuItem.Icon> <Image Source="/Resources/ManualAdd.png" Width="15" Height="15"></Image> </MenuItem.Icon> </MenuItem> 的{​​{1}}属性。如果您仍然不明白这一点,请查看WPF Tutorial.NET上的Context Menus in WPF页面。

更新&gt;&gt;&gt;

我根本不明白你为什么发布这个问题。首先,你说你做不了什么,但后来在另一篇文章中为我们提供了一个有效解决方案的链接。在试图帮助你之后,你说它确实有效,但你不知道为什么......但是你再次正确地回答了你自己的问题:

  

据我所知,问题是TreeView控件和ContextMenu的不同DataContext,因为ContextMenu有自己的VisualTree,它不是TreeView ViaualTree的一部分。

如你所说,Tag有自己的视觉树。这意味着它不知道另一个可视树中的名称或其他控件。但是,如果为TreeView提供了一个对象(如包含视图),则可以知道另一个可视树中的控件(更具体地说,是控件中的控件的可视树)。视图)。

整个问题似乎是由于您对ContextMenu的一般性和ContextMenu.DataContext语法缺乏了解。有关此主题的更多帮助,请查看MSDN上的以下文章:

Binding.Path Property

Property Path Syntax

RelativeSource MarkupExtension

很多人试图在他们走路之前使用WPF。