WPF树视图contextmenu命令参数 [英] WPF treeview contextmenu command parameter

查看:90
本文介绍了WPF树视图contextmenu命令参数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有 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。调用命令效果很好,但是我在 CommandParameter 中总是有 null 。我发现了一些与我类似的问题,但我不了解解决方案。例如:

As you can see, I bind Command to menu item. AddPackageCommand defined in ViewModell class as usually. Invoke command works fine, but I always have null in CommandParameter. I found some questions similar to my, but I don't understand solutions. For example:

ContextMenu中的CommandParameters WPF

反正它对我不起作用:(我做错了什么?

Anyway it doesn't work for me :( What am I doing wrong?

已更新

这似乎可行,但都一样,我不明白为什么 CommandParameter 不适用于 TreeView.Name

That seems to be working, but it's all the same, I don't understand why CommandParameter doesn't work with TreeView.Name.

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

例如,这样的示例可以正常工作

for examplle, such a sample works fine

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

什么是地狱...

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

And anyway, I have TreeView object in CommandParameter, not TreeViewItem. I can get SelectedItem from TreeView, but how can I send exactly TreeViewItem as 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 的一部分。

WHY sometimes I can use direct TreeView control name and sometimes I cannot. As I understand, matter is different DataContext of TreeView control and ContextMenu because ContextMenu has its own VisualTree and it is not the part of TreeView ViaualTree.

不幸的是,这种方法也行不通,我再次没有 null 。我确实设置了TreeView.Tag。

Unfortunately, that approach doesn't work too, I have null again. I set TreeView.Tag, sure.

<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中使用它了。

This is the easiest way, but if I have SelectedItem property in ViewModel it has no sense bind it to CommandParameter, because I already have it in 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>


推荐答案

您告诉我们您已经有了答案。 。为什么您实际上在同一主题上发布了另一个问题,而不是简单地按照答案中的示例进行发布?它对您不起作用,因为您没有正确复制答案。

You showed us that you already have an answer... why on earth did you post yet another question on this same subject instead of simply following the example in the answer? It doesn't work for you, because you didn't copy the answer properly.

在您的示例帖子答案中, Tag 属性设置为 TreeView 控制是否应用菜单,但您尚未执行此操作。

In your example post answer, the Tag property is set to the TreeView control that the menu is applied on, but you haven't done this.

您的下一个问题是您忽略了此 CommandParameter 中再次> Tag 属性...以某种方式,您已将其更改为正确答案:

Your next problem is that you have ignored this Tag property again in the CommandParameter... somehow, you have changed this from the correct answer:

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

在您的问题中对此:

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

您需要做的就是复制并粘贴它,同样,您可能会有更多的运气:

All you needed to do was copy and paste it. All the same, you might have even more luck doing this:

<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 ,这意味着将任何内容设置为<$ c的 DataContext $ c> TreeView 现在在 Tag 属性对象中可用。

Look at the TreeView.Tag property... this is set to its own DataContext, which means that whatever is set as the DataContext of the TreeView is now available in the Tag property object.

接下来,查看 ContextMenu.DataContext 属性...将其设置为 PlacementTarget 的> Tag 属性,这是 ContextMenu 应用于的控件,或本例中的 Treeview

Next, look at the ContextMenu.DataContext property... this is set to the Tag property of the PlacementTarget, which is the control that the ContextMenu is applied to, or in this case, the Treeview.

如果尚未解决,则意味着 DataContext 现在,> ContextMenu 设置为与 TreeView DataContext 相同的对象。如果这不是您想要的,因为您的 Command 在另一个对象上,则只需在 Binding 路径中更改 Tag 属性指向具有 Command 的对象所在的位置。

If you haven't worked it out yet, this means that the DataContext of the ContextMenu is now set to the same object as the DataContext of the TreeView. If this is not what you want because your Command is on a different object, then just change the Binding path in the Tag property to point to wherever the object that had the Command is.

最简单的事情是在视图模型/代码后面添加一个属性,该属性绑定到 TreeView.SelectedItem 属性:

The last thing that you can do to make this simpler is to add a property to your view model/code behind that binds to the TreeView.SelectedItem property:

<TreeView SelectedItem="{Binding SelectedItem}"... />

然后,您可以简单地为 CommandParameter

Then you can simply refer to this property for your 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>

当然,这最后一部分假设您将视图模型/代码设置为<$ c TreeView 的$ c> Tag 属性。如果您仍然不明白这一点,请查看WPF教程上的 WPF中的上下文菜单页。 NET。

This last part of course assumes that you have set your view model/code behind as the Tag property of the TreeView. If you still don't understand this, take a look at the Context Menus in WPF page on WPF Tutorial.NET.

更新>>>

我根本不明白您为什么发布此问题。首先,您说您无法做某事,然后在另一篇文章中为我们提供了指向有效解决方案的链接。在尝试帮助您之后,您会说它确实有效,但是您不知道为什么...但是随后您又正确地回答了自己的问题:

I simply don't understand why you posted this question. First you said you couldn't do something, but then provided us with a link to a valid solution in another post. After trying to help you, you then say that it did work, but you don't know why... but then you correctly answered your own question again:


据我了解,问题是TreeView控件和ContextMenu的DataContext不同,因为ContextMenu具有自己的VisualTree,而不是TreeView ViaualTree的一部分。

As I understand, matter is different DataContext of TreeView control and ContextMenu because ContextMenu has its own VisualTree and it is not the part of TreeView ViaualTree.

正如您所说, ContextMenu 有自己的可视树。这意味着它不知道另一个可视树中的控件(已命名还是以其他方式命名)。但是,如果 ContextMenu.DataContext 提供了诸如包含视图之类的对象,则它可以识别另一棵可视树中的控件(

As you said, the ContextMenu has its own visual tree. This means that it is not aware of controls, named or otherwise, in another visual tree. However, if the ContextMenu.DataContext is provided with an object such as the containing view, then it can be aware of controls in another visual tree (more specifically, the visual tree of the controls in the view).

整个问题似乎都归结于您对 Binding 常规, Binding.Path 语法更具体。请查看以下有关MSDN的文章,以获取有关该主题的更多帮助:

This whole issue seems to be down to a lack of knowledge on your part about Binding in general and Binding.Path syntax more specifically. Please take a look at the following articles on MSDN for more help on this topic:

Binding.Path属性

属性路径语法

RelativeSource MarkupExtension

有很多人在步行前尝试使用WPF。

So many people try to run with WPF before they can walk.

这篇关于WPF树视图contextmenu命令参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆