【问题标题】:How can I make RoutedUICommand.OnCanExecute for a command assigned to a button depend on Keyboard.FocusedElement?如何使分配给按钮的命令的 RoutedUICommand.OnCanExecute 依赖于 Keyboard.FocusedElement?
【发布时间】:2018-08-21 15:15:30
【问题描述】:

我对@9​​87654322@ 和Keyboard.FocusedElement 有疑问。

我创建了一个带有InputGesture(键盘快捷键)的命令,将其分配给MenuItemButton,并将其添加到拥有窗口的CommandBindings 中,结果如下:

  • 如果Keyboard.FocusedElement 不是DataGridCell,按钮/菜单将被禁用。
  • 我可以单击菜单并执行命令,聚焦的DataGridCell 保持聚焦。
  • 如果焦点位于DataGridCell 上,我可以使用键盘快捷键并执行命令。

我无法解决的是以下问题:

  • 我无法通过单击按钮触发命令,因为(显然)单击导致OnCanExecute 失败,因为Keyboard.FocusedElement 是按钮。

但奇怪的是:如果我通过始终设置e.CanExecute = true 来禁用OnCanExecute 方法,则不会出现上述问题,并且在OnExecutedKeyboard.FocusedElement 确实是DataGridCell

在我为寻找解决方案而访问的所有网站中,https://blogs.msdn.microsoft.com/mikehillberg/2009/03/20/icommand-is-like-a-chocolate-cake/ 非常有趣(尤其是 ToolBar 是一个“焦点范围”),但这还不足以帮助我解决问题我的问题。

这里是相关的(和缩写的)代码 sn-ps。

应该与当前选定的DataGridCell 一起使用的命令:

public class MyDataGridCellCommand : RoutedUICommand
{
    public MyDataGridCellCommand()
    {
        this.InputGestures.Add(new KeyGesture(Key.F1));
        this.Text = "Process selected cell";
    }

    public void OnExecuted(object sender, ExecutedRoutedEventArgs e)
    {
        if(Keyboard.FocusedElement is DataGridCell cell){
            //Process selected cell...
        }
    }

    public void OnCanExecute(object sender, CanExecuteRoutedEventArgs e)
    {
        e.CanExecute = (Keyboard.FocusedElement is DataGridCell);
    }
}

窗口的 Xaml:

<Window x:Class="MainWindow" Title="MainWindow" Height="450" Width="800">
    <Grid>
        <StackPanel Orientation="Vertical" >
            <Menu>
                <MenuItem x:Name="menuTest"></MenuItem>
            </Menu>
            <StackPanel Orientation="Horizontal">
                <!--Button in "default" stackpanel -->
                <StackPanel  Orientation="Horizontal"  >
                    <Button x:Name ="btnTest1" Content="Test1"/>
                </StackPanel>

               <!--Button in "focus scope" stackpanel -->
                <StackPanel  Orientation="Horizontal" FocusManager.IsFocusScope="True" >
                    <Button x:Name ="btnTest2" Content="Test2"/>
                </StackPanel>

                <!--Button in toolbar-->
                <ToolBar x:Name ="toolBar1" Focusable="True">
                    <Button x:Name ="btnTest3" Content="Test3" Margin="5,0,5,0"/>
                </ToolBar>
            </StackPanel>

            <DataGrid>
                <!--Layout Attributes removed for brevity. -->
            </DataGrid>
        </StackPanel>
    </Grid>
</Window>

窗口的代码隐藏:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

        var cmd = new MyDataGridCellCommand();

        this.CommandBindings.Add(new CommandBinding(cmd, cmd.OnExecuted, cmd.OnCanExecute));

        this.btnTest1.Command = cmd;
        this.btnTest2.Command = cmd;
        this.btnTest3.Command = cmd;
        this.menuTest.Command = cmd;

        this.DataContext = this;
    }
}

【问题讨论】:

    标签: c# wpf binding routed-commands


    【解决方案1】:

    如果您不需要将焦点放在测试按钮上,我只需在 btnTest1 上设置 Focusable="False"。

    如果您仍然希望按钮可聚焦,一个想法可能是不使用 Keyboard.FocusedElement 而是使用 FocusManager.GetFocusedElement,如下所示:

    public class MyDataGridCellCommand : RoutedUICommand
    {
        public MyDataGridCellCommand()
        {
            this.InputGestures.Add(new KeyGesture(Key.F1));
            this.Text = "Process selected cell";
    
        }
    
        public void OnExecuted(object sender, ExecutedRoutedEventArgs e)
        {
            if (FocusManager.GetFocusedElement(sender as DependencyObject) is DataGridCell) {
                //Process selected cell...
            }
        }
    
        public void OnCanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = (FocusManager.GetFocusedElement(sender as DependencyObject) is DataGridCell);
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2016-11-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-08-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多