【发布时间】:2018-08-21 15:15:30
【问题描述】:
我对@987654322@ 和Keyboard.FocusedElement 有疑问。
我创建了一个带有InputGesture(键盘快捷键)的命令,将其分配给MenuItem 或Button,并将其添加到拥有窗口的CommandBindings 中,结果如下:
- 如果
Keyboard.FocusedElement不是DataGridCell,按钮/菜单将被禁用。 - 我可以单击菜单并执行命令,聚焦的
DataGridCell保持聚焦。 - 如果焦点位于
DataGridCell上,我可以使用键盘快捷键并执行命令。
我无法解决的是以下问题:
- 我无法通过单击按钮触发命令,因为(显然)单击导致
OnCanExecute失败,因为Keyboard.FocusedElement是按钮。
但奇怪的是:如果我通过始终设置e.CanExecute = true 来禁用OnCanExecute 方法,则不会出现上述问题,并且在OnExecuted 内Keyboard.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