我想将某个命令绑定到menuItem
。所述菜单项是在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 :(得分: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>
ContextMenu并不存在于常规的Visual Tree中,因此您无法走到树上以进入主数据上下文。通过使用标签,您可以传入&#34;主窗口的数据上下文到上下文菜单。有关使用上下文菜单进行绑定的更多信息,请参阅this answer以及this one,因为它们提供了有关正在发生的事情的一些很好的解释