2016-03-16 3 views
2

Я хочу связать определенную команду с menuItem. Указанный пункт меню является частью ContextMenu, который определен внутри ItemTemplate.Как связать команду с ContextMenu изнутри ItemTemplate?

Прямо сейчас, что я компилирую и запускаю, но команда никогда не вызывается. Раньше я использовал аналогичный шаблон для успешной привязки команд к кнопкам, определенным в ItemTemplate.

Кто-нибудь знает, как я мог это сделать?

XAML:

<Window 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:local="clr-namespace:Wpf_treeView" x:Name="window" x:Class="Wpf_treeView.MainWindow" 
    Title="MainWindow" Height="350" Width="525"> 
    <Grid> 
    <TreeView HorizontalAlignment="Left" Height="299" Margin="10,10,0,0" VerticalAlignment="Top" Width="228" ItemsSource="{Binding DataInfosView}" > 
     <TreeView.ItemTemplate> 
     <HierarchicalDataTemplate ItemsSource="{Binding Children}"> 
      <TextBlock DockPanel.Dock="Left" Text="{Binding InfoValue}" TextAlignment="Left" > 
      <TextBlock.ContextMenu> 
       <ContextMenu> 
       <MenuItem Header="{Binding InfoValue}" IsEnabled="False"/> 
       <MenuItem Header="Add child" Command="{Binding AddChildCmd, ElementName=window}"/> 
       </ContextMenu> 
      </TextBlock.ContextMenu> 
      </TextBlock> 
     </HierarchicalDataTemplate> 
     </TreeView.ItemTemplate> 
    </TreeView> 
    </Grid> 
</Window> 

C#:

using System; 
using System.Collections.Generic; 
using System.Windows; 
using System.Windows.Data; 
using System.Windows.Input; 

namespace Wpf_treeView 
{ 
    public partial class MainWindow : Window 
    { 
     private static readonly Random rnd = new Random(); 
     private List<InfoData> m_InfoData = new List<InfoData>(); 

     public ListCollectionView DataInfosView { get; private set; } 

     public static readonly DependencyProperty AddChildProperty = 
      DependencyProperty.Register("AddChildCmd", 
             typeof(ICommand), 
             typeof(MainWindow)); 

     public ICommand AddChildCmd 
     { 
      get { return (ICommand) GetValue(AddChildProperty); } 
      set { SetValue(AddChildProperty, value); } 
     } 

     public MainWindow() 
     { 
      AddChildCmd = new RoutedCommand(); 
      CommandManager.RegisterClassCommandBinding(
       GetType(), 
       new CommandBinding(AddChildCmd, AddChild)); 

      m_InfoData.Add(new InfoData(4)); 
      m_InfoData.Add(new InfoData(1)); 
      m_InfoData.Add(new InfoData(5)); 
      m_InfoData[1].Children.Add(new InfoData(3)); 
      m_InfoData[1].Children[0].Children.Add(new InfoData(7)); 

      DataInfosView = new ListCollectionView(m_InfoData); 
      DataContext = this; 

      InitializeComponent(); 
     } 

     private void AddChild(object sender, RoutedEventArgs e) 
     { 
      ExecutedRoutedEventArgs args = (ExecutedRoutedEventArgs)e; 
      InfoData info = (InfoData)args.Parameter; 
      info.Children.Add(new InfoData(rnd.Next(0, 11))); 
     } 
    } 

    class InfoData : INotifyPropertyChanged 
    { 
     private int infoValue; 

     public int InfoValue 
     { 
      get { return infoValue; } 
      set 
      { 
       if (value != infoValue) 
       { 
        infoValue = value; 
        OnPropertyChanged(); 
       } 
      } 
     } 

     public List<InfoData> Children { get; private set; } 

     public InfoData(int infoValue) 
     { 
      InfoValue = infoValue; 
      Children = new List<InfoData>(); 
     } 

     public event PropertyChangedEventHandler PropertyChanged; 

     protected virtual void OnPropertyChanged(
      [CallerMemberName] string propertyName = null) 
     { 
      if (PropertyChanged != null) 
       PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
     } 
    } 
} 
+0

Вы получаете ошибки привязки для команды? –

+0

Нет. Все компилируется и работает нормально. Меню также прекрасно выглядит. Просто команда не вызывается. Кстати, мне было бы неплохо иметь дело с событием (Click), но мне нужно было бы получить доступ к элементу, который был создан в меню, и я не уверен, как получить доступ к нему. – joce

+2

Ошибка привязки не вызовет каких-либо проблем с компиляцией или вызовет какие-либо проблемы с отображением, она просто появится в окне вывода при использовании отладчика, их можно будет легко упустить, но они очень полезны для отладки проблем xaml, таких как привязка. –

ответ

1

Хорошо это должно работать:

<TextBlock DockPanel.Dock="Left" 
          Text="{Binding InfoValue}" 
          TextAlignment="Left" 
          Tag="{Binding RelativeSource={RelativeSource AncestorType={x:Type Window}}}"> 
        <TextBlock.ContextMenu> 
         <ContextMenu> 
          <MenuItem Header="{Binding InfoValue}" 
             IsEnabled="False" /> 
          <MenuItem Header="Add child" 
             Command="{Binding Path=Parent.PlacementTarget.Tag.AddChildCmd, RelativeSource={RelativeSource Self}}" 
             CommandParameter="{Binding}" /> 
         </ContextMenu> 
        </TextBlock.ContextMenu> 
       </TextBlock> 

Контекстное не существует в обычном визуальном дереве, так что вы Арен» t можно подойти к дереву, чтобы перейти к основному контексту данных. Используя тег, вы можете «передать» контекст данных главного окна в контекстное меню. Для получения дополнительной информации о привязке к контекстному меню см. this answer, а также this one, так как они дают некоторые полезные пояснения относительно того, что происходит

+0

Он работает больше, чем раньше, но он все равно не работает. : -/Пункт меню, отображающий значение элемента, ничего не отображает. И команда * IS * вызывается, но стараюсь, как я могу, я не могу передать выбранный элемент в качестве параметра (я думаю, эта проблема аналогична той, где я не могу отобразить значение элемента). Это заставляет меня думать, что я не могу объявить «ContextMenu» в нужном месте. – joce

+0

была ошибка привязки для пункта меню, который не отображался? –

+0

Нет. :-(Нет ошибок – joce