zoukankan      html  css  js  c++  java
  • HierarchicalDataTemplate中的ContextMenu的Command绑定

    <ContextMenu x:Key="ModeMenu">
    <MenuItem Header="添加" Command="{Binding AddCommand}"
    CommandParameter="{Binding ElementName=ModesTree, Path=SelectedItem}">
    <MenuItem.Icon>
    <Image Source="../Images/Add.png" Width="16" Height="16" />
    </MenuItem.Icon>
    </MenuItem>
    </ContextMenu>

    <HierarchicalDataTemplate x:Key="ModeTemplate" DataType="{x:Type Model:ModeInfo}" ItemsSource="{Binding Path=PlanInfoList}" >
    <StackPanel Orientation="Horizontal" ContextMenu="{StaticResource ModeMenu}"
    DataContext="{Binding RelativeSource={RelativeSource TemplatedParent}}">
    <Image x:Name="imgStatus" Source="../Images/Add.png" Width="16" Height="16" />
    <TextBlock Margin="2,0,0,0" VerticalAlignment="Center" FontWeight="Bold" Text="{Binding ModeName}" />
    </StackPanel>
    </HierarchicalDataTemplate>

    如代码所示,这个MenuItem的Command并不起作用。网上有人给出的解释是:ContentMenu是作为你一个popup的窗口出现在UI上的,因此,这个Popup和原来的窗口并不是同一个VisualTree,既然不在同一个VisualTree中,则无法找到DataContext。

    解决方法如下:

    定义一个类CommandReference:

    public class CommandReference : Freezable, ICommand, ICommandSource
    {
    public CommandReference()
    {

    }

    public static readonly DependencyProperty CommandParameterProperty =
    DependencyProperty.Register(
    "CommandParameter",
    typeof(object),
    typeof(CommandReference),
    new PropertyMetadata((object)null));

    public object CommandParameter
    {
    get
    {
    return (object)GetValue(CommandParameterProperty);
    }
    set
    {
    SetValue(CommandParameterProperty, value);
    }
    }

    public static readonly DependencyProperty CommandTargetProperty =
    DependencyProperty.Register(
    "CommandTarget",
    typeof(IInputElement),
    typeof(CommandReference),
    new PropertyMetadata((IInputElement)null));

    public IInputElement CommandTarget
    {
    get
    {
    return (IInputElement)GetValue(CommandTargetProperty);
    }
    set
    {
    SetValue(CommandTargetProperty, value);
    }
    }

    public static readonly DependencyProperty CommandProperty = DependencyProperty.Register("Command", typeof(ICommand), typeof(CommandReference), new PropertyMetadata(new PropertyChangedCallback(OnCommandChanged)));

    public ICommand Command
    {
    get { return (ICommand)GetValue(CommandProperty); }
    set { SetValue(CommandProperty, value); }
    }

    #region ICommand Members

    public bool CanExecute(object parameter)
    {
    if (Command != null)
    return Command.CanExecute(CommandParameter);
    return false;
    }

    public void Execute(object parameter)
    {
    Command.Execute(CommandParameter);
    }

    public event EventHandler CanExecuteChanged;

    private static void OnCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
    CommandReference commandReference = d as CommandReference;
    ICommand oldCommand = e.OldValue as ICommand;
    ICommand newCommand = e.NewValue as ICommand;

    if (oldCommand != null)
    {
    oldCommand.CanExecuteChanged -= commandReference.CanExecuteChanged;
    }
    if (newCommand != null)
    {
    newCommand.CanExecuteChanged += commandReference.CanExecuteChanged;
    }
    }

    #endregion

    #region Freezable

    protected override Freezable CreateInstanceCore()
    {
    throw new NotImplementedException();
    }

    #endregion
    }

    然后修改View中的代码,先插入一个CommandReference资源,将其绑定到命令,再将菜单的命令绑定到资源,如下所示:

    <UserControl.Resources>
    <c:CommandReference x:Key="AddModeCommandRef" Command="{Binding Path=AddModeCommand}"/>
    <ContextMenu x:Key="RootMenu" >
    <MenuItem Header="添加" Command="{StaticResource AddModeCommandRef}" >
    <MenuItem.Icon>
    <Image Source="../Images/Add.png" Width="16" Height="16" />
    </MenuItem.Icon>
    </MenuItem>
    </ContextMenu>
    <HierarchicalDataTemplate x:Key="ModeTemplate" DataType="{x:Type Model:ModeInfo}" ItemsSource="{Binding Path=PlanInfoList}" >
    <StackPanel Orientation="Horizontal" ContextMenu="{StaticResource ModeMenu}" DataContext="{Binding RelativeSource={RelativeSource TemplatedParent}}"> <Image x:Name="imgStatus" Source="../Images/Add.png" Width="16" Height="16" />
    <TextBlock Margin="2,0,0,0" VerticalAlignment="Center" FontWeight="Bold" Text="{Binding ModeName}" />
    </StackPanel>
    </HierarchicalDataTemplate>

    最后在ViewModel中定义命令即可:

    public ICommand AddModeCommand { get; set; }

    参考文章:

    http://social.msdn.microsoft.com/Forums/zh-SG/wpfzhchs/thread/13bcc6e4-d3f7-40c8-a9e8-ee35918edc14

    http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/36ce07fc-64de-4dc9-8012-3c4f03605c30/

  • 相关阅读:
    从零开始学习前端开发 — 17、CSS3背景与渐变
    从零开始学习前端开发 — 16、CSS3圆角与阴影
    从零开始学习前端开发 — 15、CSS3过渡、动画
    从零开始学习前端开发 — 14、CSS3变形基础
    link标签的media属性的用法
    html的meta总结
    提高网页可访问性的十条建议
    关闭按钮
    HTTP协议详解
    jquery中each的3种遍历方法
  • 原文地址:https://www.cnblogs.com/wenjingu/p/2248278.html
Copyright © 2011-2022 走看看