2014-11-20 5 views
0

Я использую шаблон команды с (между прочим) контекстным меню в TreeViewItem, который использует HierarchicalDataTemplates. MainWindowViewModel (статический ресурс для окна) имеет свойства, которые выставляют одноэлементные объекты, которые, в свою очередь, имеют свойства, которые представляют команды. Я могу выполнить команду очень хорошо, но некоторые из команд должны передать DataContext TreeViewItem как CommandParameter.WPF Databinding ContextMenuItem's CommandParameter для DataContext TreeViewItem

Вот пример: Один узел дерева имеет элемент ItemsSource, связанный с ObservableCollection отдельных объектов AnalysisMain. Каждый из результирующих поднодов имеет ContextMenu (с DataContext, связанным с AnalysisController), который имеет (помимо прочего) Remove MenuItem. Свойство Remove MenuItem Command связано с командой CommandRemove объекта SingleControlController (и он выполняется просто отлично). Но это также требует, чтобы CommandParameter привязывался к объекту AnalysisMain, который служит DataContext для подузлов в дереве. Я попытался с помощью RelativeSource с AncestorType, установленным в TreeViewItem и Путь установлен в DataContext:

<HierarchicalDataTemplate DataType="{x:Type vmAnalysis:AnalysisMain}"> 
    <WrapPanel Orientation="Horizontal"> 
     <Image Source="Analysis\Icon_Analysis_Main_16_Normal.png" Margin="0,0,2,0" Width="16"/> 
     <TextBlock Text="{Binding TreeViewTitle}"> 
      <TextBlock.ContextMenu> 
       <ContextMenu DataContext="{StaticResource mainWindowViewModel}"> 
        <MenuItem Header="Remove" Command="{Binding Path=AnalysisController.CommandRemove}" 
           CommandParameter="{Binding RelativeSource={RelativeSource AncestorType={x:Type TreeViewItem}, AncestorLevel=4}, Path=DataContext}"> 
        </MenuItem> 
       </ContextMenu> 
      </TextBlock.ContextMenu> 
     </TextBlock> 
    </WrapPanel> 
</HierarchicalDataTemplate> 

без AncestorLevel набора, когда я открываю ContextMenu, я получаю следующее в окне Output:

System.Windows.Data Error: 4 : Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='System.Windows.Controls.TreeViewItem', AncestorLevel='4''. BindingExpression:Path=DataContext; DataItem=null; target element is 'MenuItem' (Name=''); target property is 'CommandParameter' (type 'Object')

Я пробовал несколько значений для AncestorLevel безрезультатно.

Изучив визуальное дерево в инспекторе Христиана Мозера WPF, я не вижу контекстного меню в визуальном дереве. Хотя TreeViewItem показывает объект DataContext. Мне просто нужен способ «ориентироваться» на него, чтобы привязываться к нему.


В качестве альтернативы, я попытался оставить ContextMenu DataContext один и настройки команды Binding Source-х, чтобы указать назад к AnalysisController. Это также работает для выполнения команды, но я не способен связываться с DataContext в TreeViewItem для в CommandParameter:

<ContextMenu> 
    <MenuItem Header="Remove" Command="{Binding Source={StaticResource mainWindowViewModel}, Path=AnalysisController.CommandRemove}" 
       CommandParameter="{Binding Source={RelativeSource Self}, Path=DataContext}"> 
    </MenuItem> 
</ContextMenu> 

Я также попытался просто использовать CommandParameter = «{Binding}», который также не работает , (В обоих случаях я просто получаю null в качестве параметра. В окне вывода не записывается предупреждение/ошибка.) EDIT: для кого-либо еще с этой проблемой второй вариант был обречен с самого начала, потому что я ошибочно положил Source = {RelativeSource Self}, который будет ссылаться на MenuItem, а не на TreeViewItem. Однако изменение этого параметра с AncestorType/AncestorLevel не имеет значения.

+0

я могу ошибаться о точной ошибки связанной к 'CommandParameter', на самом деле параметр имеет значение null внутри' CanExecute' (что означает, что Binding не работает), но внутри 'Execute' callback, параметр передается OK. Для ранее опубликованного кода вы можете попробовать посмотреть в окне «Выход», чтобы узнать, есть ли там какая-либо ошибка. –

+0

Я проверил (переопределить CanExecute, чтобы всегда возвращать true), и параметр по-прежнему равен нулю. – Tim

ответ

1

Вы должны использовать PlacementTarget свойство ContextMenu

<Setter Property="ContextMenu"> 
     <Setter.Value> 
      <ContextMenu 
     DataContext="{Binding PlacementTarget.DataContext, RelativeSource={RelativeSource Self}}"> 
      </ContextMenu> 
     </Setter.Value> 
</Setter> 

и на Вашем MenuItem сделать RelativeSource к ContextMenu затем использовать PlacementTarget.DataContext как ваше связывание с вашим CommandParameter

+0

Нужно ли использовать Setter вместо того, чтобы просто установить свойство? (Я знаком с сеттерами только при использовании с триггерами.) Вот что я закончил с: (on ContextMenu) DataContext = "{Binding PlacementTarget.DataContext, RelativeSource = {RelativeSource Self}} "и в MenuItem CommandParameter =" {Binding RelativeSource = {RelativeSource AncestorType = {x: Тип ContextMenu}}, Path = PlacementTarget.DataContext} " – Tim

+0

@Tim Вы можете напрямую использовать свойство, У меня просто был фрагмент, который использует стили –

+0

Кто бы ни проголосовал, скажите, пожалуйста, почему? –

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

  • Нет связанных вопросов^_^