假设:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.CommandBindings>
<CommandBinding Command="Cut"
Executed="CommandBinding_Executed"/>
</Grid.CommandBindings>
<TextBox x:Name="WpfTextBox"
VerticalAlignment="Center"
Text="Hello there" />
<WindowsFormsHost Grid.Column="1"
VerticalAlignment="Center">
<wf:TextBox x:Name="WinFormsTextBox"
Text="Hello there" />
</WindowsFormsHost>
</Grid>
在WinFormsTextBox
中按 Ctrl + X 会导致CommandBinding_Executed
触发,但在WpfTextBox
时不会。
我希望WpfTextBox
的行为WinFormsTextBox
。即该命令只应在没有焦点的情况下触发 - 它应该像全局视图命令一样工作。
注意:在命令的CanExecute
事件中添加处理程序只会有助于阻止WinFormsTextBox
中发生任何事情( Ctrl + X 当e.CanExecute
设置为true
时 - 意味着没有剪切文字),或完全正常执行时完全被吞下。
注2:剪切只是一个例子,我想要一个适用于任何命令绑定的解决方案。
注3:如果命令具有焦点,该命令应该能够从另一个控件触发 - 如ListView或其他东西。除非它有一个焦点在其中的TextBox(想想编辑模式)。
我不确定能做什么,我不想接受在CommandBinding_Executed
方法中添加特定处理。但是,C'est la vie。
答案 0 :(得分:0)
路由WPF命令,并在WindowsFormsHost的父控件中为Ctrl + X命令定义了CommandBinding。因此,如果您希望仅在WPF TextBox中处理它,请从Grid中删除CommandBinding并将其放在那里:
<TextBox>
<TextBox.CommandBindings>
<CommandBinding Command="Cut"
Executed="CommandBinding_Executed"/>
</TextBox.CommandBindings>
</TextBox>
在路由命令时,Ctrl + X命令将由具有此命令绑定的第一个父级处理。只要您的焦点位于Grid的范围内并执行Ctrl + X命令,Grid命令绑定就会处理它。
以下是关于WPF中路由事件和命令的优秀文章:Understanding Routed Events and Commands In WPF
修改强>
如果您不希望在TextBox中处理该命令,则只需在Ctrl + X对您有意义的情况下定义CommandBindings。我认为你没有其他解决方案。无论如何,通常像Cut这样的ApplicationCommands是特定范围的上下文,例如RichTextBox或ListBox。
修改强>
您无法阻止WindowsFormsHost触发基础路由命令。但是你可以做的只是从CommandBindings范围中删除主机:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid Grid.Column="0">
<Grid.CommandBindings>
<CommandBinding Command="Cut"
Executed="CommandBinding_Executed"/>
</Grid.CommandBindings>
<TextBox x:Name="WpfTextBox"
VerticalAlignment="Center"
Text="Hello there" />
</Grid>
<WindowsFormsHost Grid.Column="1"
VerticalAlignment="Center">
<wf:TextBox x:Name="WinFormsTextBox"
Text="Hello there" />
</WindowsFormsHost>
</Grid>
当然,如果你有更多的对象要布局,它可能会有点棘手,但它会起作用。只需从CommandBindings的范围中删除您不想处理命令的对象。
答案 1 :(得分:0)
private void CommandBinding_CanExecute(object sender, CanExecuteRoutedEventArgs e)
{
e.ContinueRouting = IsFocusInWinFormsInputControl();
}
private static bool IsFocusInWinFormsInputControl()
{
// Try get focus control
WinForms.Control focusedWinFormsControl = GetFocusedWinFormsControl();
// Is there anything and is it a textbox etc?
return focusedWinFormsControl != null &&
(focusedWinFormsControl is WinForms.TextBox ||
focusedWinFormsControl is WinForms.RichTextBox);
}
private static WinForms.Control GetFocusedWinFormsControl()
{
// Try get focused WinForms control
IntPtr focusedControlHandle = GetFocus();
WinForms.Control focusedControl = null;
if (focusedControlHandle != IntPtr.Zero)
{
// Note: If focused Control is not a WinForms control, this will return null
focusedControl = WinForms.Control.FromHandle(focusedControlHandle);
}
return focusedControl;
}
[DllImport("user32.dll")]
private static extern IntPtr GetFocus();
基本上,如果我们在WinForms TextBox之外,请添加命令验证逻辑以仅执行命令。