2013-10-02 96 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