I want to bind a certain command to a menuItem
. The said menu item is part of a ContextMenu
that is defined inside an ItemTemplate
.
Right now, what I have compiles and runs, but the command is never called. In the past, I had used a similar pattern to hook commands to buttons defined in an ItemTemplate
with success.
Anyone has any idea how I could accomplish this?
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));
}
}
}