簡體   English   中英

如何從 ItemTemplate 中將命令綁定到 ContextMenu?

[英]How to bind a Command to a ContextMenu from within an ItemTemplate?

我想將某個命令綁定到menuItem 所述菜單項是在ItemTemplate內定義的ContextMenu一部分。

現在,我編譯並運行的內容,但從未調用過該命令。 過去,我曾使用類似的模式成功地將命令掛鈎到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));
        }
    }
}

好吧,這應該有效:

<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>

ContextMenu 不存在於常規可視化樹中,因此您無法沿着樹向上走以到達主數據上下文。 通過使用標簽,您可以將主窗口的數據上下文“傳入”上下文菜單。 有關使用上下文菜單中的綁定一些詳細信息,請參閱這個答案,以及這一個,因為他們提供一些好的解釋為這是怎么回事

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM