代码之家  ›  专栏  ›  技术社区  ›  repka

avalondock+usercontrol+datagrid+contextmenu命令路由问题

  •  3
  • repka  · 技术社区  · 15 年前

    我的命令传播行为很奇怪 MenuItems 属于 ContextMenu .

    我有以下类型的布局: 上下文菜单 为每个设置 DataGridRow 属于 DataGrid 里面 UserControl ,它依次在里面 DockableContent 阿瓦隆克的如果我摆脱 任何一个 对接或 用户控制 在我的网格周围没有问题。 ListBox 而不是 数据网格 也没有这个问题。

    <Window x:Class="DockAndMenuTest.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:ad="clr-namespace:AvalonDock;assembly=AvalonDock"
            Title="MainWindow" Height="350" Width="525">
        <ad:DockingManager>
            <ad:DocumentPane>
                <ad:DockableContent Title="Doh!">
                    <UserControl>
                        <UserControl.CommandBindings>
                            <CommandBinding Command="Zoom" 
                                            Executed="ExecuteZoom" 
                                            CanExecute="CanZoom"/>
                        </UserControl.CommandBindings>
                        <DataGrid Name="_evilGrid">
                            <DataGrid.Resources>
                                <Style TargetType="DataGridRow">
                                    <Setter Property="ContextMenu">
                                        <Setter.Value>
                                            <ContextMenu>
                                                <MenuItem Command="Zoom"/>
                                            </ContextMenu>
                                        </Setter.Value>
                                    </Setter>
                                </Style>
                            </DataGrid.Resources>
                        </DataGrid>
                    </UserControl>
                </ad:DockableContent>
            </ad:DocumentPane>
        </ad:DockingManager>
    </Window>
    

    代码隐藏也很简单:

    public partial class MainWindow
    {
        public MainWindow()
        {
            InitializeComponent();
    
            _evilGrid.ItemsSource =
                new[]
                    {
                        Tuple.Create(1, 2, 3),
                        Tuple.Create(4, 4, 3),
                        Tuple.Create(6, 7, 1),
                    };
        }
    
        private void ExecuteZoom(object sender, ExecutedRoutedEventArgs e)
        {
            MessageBox.Show("zoom !");
        }
    
        private void CanZoom(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = true;
        }
    }
    

    所以问题是:右键单击选中的行(如果在右键单击之前选中了该行),我的命令将被禁用。在这种情况下,命令是“缩放”,但可以是任何其他命令,包括自定义命令。

    我不知道这里有什么错。snoop显示,在这种传播失败的情况下,而不是 用户控制 , CanExecute 由“part_ShowContextMenuButton”(按钮)处理,该按钮是停靠标题的一部分。

    我对内部的UI命令传播还有其他问题 UserControls 托管在Avalondock中,但这是最容易复制的。

    1 回复  |  直到 15 年前
        1
  •  2
  •   Arcturus    15 年前

    ContextMenu是一个弹出窗口,因此将FocusScope Attached属性设置为true:

    MSDN

    焦点范围是容器元素 跟踪 FocusManager..:.FocusedElement内部 其范围。默认情况下,窗口 类和 菜单、上下文菜单和工具栏 类。焦点元素 作用域的IsFocusScope设置为False。

    基本上,它还告诉命令停止在可视化树中进一步查看。

    所以你有两个选择

    1. 设置 FocusManager.IsFocusScope="True" 在上下文菜单对象上

    2. 或者移动命令绑定,使其绑定到ContextMenu而不是像这样的UserControl:

    代码示例:

    <ContextMenu FocusManager.IsFocusScope="False">
        <ContextMenu.CommandBindings>
            <CommandBinding Command="Zoom" 
                    Executed="ExecuteZoom" 
                    CanExecute="CanZoom"/>
        </ContextMenu.CommandBindings>
             <MenuItem Command="Zoom"/>
    </ContextMenu>
    

    希望这有帮助!:)

    一些焦点在互联网上关注来自现场的噩梦故事: