2013-10-02 17 views
1

У меня есть TreeView с HierarchicalDataTemplate. На TreeView у меня есть ContextMenuWPF 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 к пункту меню. AddPackageCommand, как обычно, определен в классе ViewModell. Команда Invoke работает нормально, но у меня всегда есть null в CommandParameter. Я нашел некоторые вопросы, похожие на мои, но я не понимаю решений. Например:

CommandParameters in ContextMenu in WPF

В любом случае это не работает для меня :(Что я делаю неправильно

Обновлено

Это, кажется, работает, но это все равно Я не понимаю, почему CommandParameter не работает с TreeView.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. Я могу получить SelectedItem от TreeView, но как я могу отправить точно 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 недвижимость в ViewModel не имеет никакого смысла, привязать его к 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> 
+0

этот материал настолько излишне сложный – hinst

ответ

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 сейчас доступный в объекте недвижимости Tag.

Далее, посмотрите на ContextMenu.DataContext недвижимости ... это устанавливается в Tag свойство PlacementTarget, который является контроль, что ContextMenu применяется, или в этом случае Treeview.

Если вы еще не работали его еще, это означает, что DataContext из ContextMenu теперь устанавливается на тот же объект, как DataContext в TreeView. Если это не то, что вы хотите, потому что ваш Command находится на другом объекте, просто измените путь Binding в свойстве Tag, чтобы указать, где находится объект с 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> 

Эта последняя часть, конечно, предполагает, что вы установили вид модели/код позади как Tag свойство TreeView. Если вы все еще не понимаете этого, взгляните на страницу Context Menus in WPF в WPF Tutorial.NET.

UPDATE >>>

Я просто не понимаю, почему ты отвечал на этот вопрос. Сначала вы сказали, что не можете что-то сделать, но затем предоставили нам ссылку на действующее решение в другом сообщении. После того, как вы попытаетесь помочь вам, вы тогда скажете, что это действительно сработало, но вы не знаете, почему ... но затем вы правильно ответили на свой собственный вопрос:

Как я понимаю, материя отличается от DataContext TreeView control и 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, даже тогда у меня есть null в 'CommandParameter' :( thx в любом случае. – monstr

+0

Потому что * вы * не могли заставить мой пример работать. * Не * означает, что он не работает.Это просто означает, что вы этого не понимаете.Если вы нашли время, чтобы изучить синтаксис «Binding», как я предложил, то, возможно, вы поймете это. – Sheridan

Смежные вопросы