2013-10-02 91 views
1

我有TreeViewHierarchicalDataTemplate。在TreeViewContextMenuWPF 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。 Invoke命令可以正常工作,但我总是在CommandParameter中有null。我发现了一些类似于我的问题,但我不明白解决方案。例如:?

CommandParameters in ContextMenu in WPF

反正它不为我工作:(我在做什么错

更新

这似乎是工作,但它是完全一样的,我不明白为什么CommandParameterTreeView.Name工作。

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

为examplle,这样的样本工作正常

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

什么是地狱......

反正我有TreeView对象CommandParameter,不TreeViewItem。我可以从TreeView得到SelectedItem,但是我怎样才能发送TreeViewItem作为CommandParameter

到谢里登

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

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

而且这个工程

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

为什么有时我可以直接使用TreeView控件的名字,有时我不能。 据我所知,物质是不同的DataContext的TreeView控制和ContextMenu,因为ContextMenu有它自己的VisualTree,它不是TreeViewViaualTree的一部分。

不幸的是,那种方法也不能工作了,我又有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> 

这是最简单的方法,但如果我有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> 
+0

这东西是如此不必要的复杂 – hinst

回答

1

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

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

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

这样::

你的下一个问题是,您在CommandParameter再次忽略了这个Tag财产......不知何故,你已经在正确的答案改变了这一

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,这意味着,无论设置为TreeViewDataContext现可用于Tag属性对象。

接下来,看看ContextMenu.DataContext财产......这是设置为PlacementTargetTag属性,这是该ContextMenu被应用到,或在这种情况下,Treeview控制。

如果您还没有解决问题,这意味着ContextMenuDataContext现在被设置为与TreeViewDataContext相同的对象。如果这不是您想要的,因为您的Command位于不同的对象上,那么只需将Tag属性中的Binding路径更改为指向具有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> 

当然最后这部分假设您已经设置您的视图模型/代码背后的TreeViewTag财产。如果您仍然不明白,请查看WPF Tutorial.NET上的Context Menus in WPF页面。

UPDATE >>>

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

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

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

这整个问题似乎都是由于缺乏关于Binding一般的知识和Binding.Path语法的知识。请看一看MSDN上的以下文章以获得更多帮助有关此主题:

Binding.Path Property

Property Path Syntax

RelativeSource MarkupExtension

所以很多人尝试使用WPF运行,他们可以走了。

+0

看看更新plz – monstr

+0

---试图帮助你后,你说它确实工作,但你不知道为什么。 **没有**,我说**你的**方法不起作用。 (我复制你的代码)。绑定DataContext到TreeView.Tag等方法。在我发布的链接中被建议作为答案的方法。即使我将ContextMenu.DataContext属性设置为TreeView.Tag,即使此时我在CommandParameter中也有null :( thx无论如何。 – monstr

+0

因为* you *无法让我的示例工作,所以* not *表示它的作用如果你花时间学习像我所建议的'Binding'语法,那么也许你会明白它 – Sheridan