Wpf 从WindowsFormsHost打开时,关联菜单不会响应按键
当焦点位于WindowsFormsHost中且上下文菜单打开时,上下文菜单不会响应上/下箭头键的按下 以下代码(几乎是独立的)说明了该问题: 这将显示两个文本框,一个WPF和一个WinForms。如果按Ctrl-T键,将出现一个简单的上下文菜单 现在运行程序Wpf 从WindowsFormsHost打开时,关联菜单不会响应按键,wpf,keyboard,contextmenu,windowsformshost,Wpf,Keyboard,Contextmenu,Windowsformshost,当焦点位于WindowsFormsHost中且上下文菜单打开时,上下文菜单不会响应上/下箭头键的按下 以下代码(几乎是独立的)说明了该问题: 这将显示两个文本框,一个WPF和一个WinForms。如果按Ctrl-T键,将出现一个简单的上下文菜单 现在运行程序 将光标放在WPF文本框中 按Ctrl-T键:将显示关联菜单 按向下箭头:选择关联菜单中的第一项(“aaa”) 鉴于 将光标放在WinForms文本框中 按Ctrl-T键:将显示关联菜单 按下向下箭头:什么也没有发生 在我们的应用程序中,键盘
Keyboard.FocusedElement==null
似乎有效)。这意味着,在WinForms组件中有焦点的情况下,我的解决方案只是次优的,打开上下文菜单并选择不更改选项卡。这是罕见的,所以它比我的第一个问题有了很大的改进
但我仍然好奇是否存在更好的解决方案。我尝试了您的示例应用程序,并注意到当在WPF textBox中使用光标打开contextMenu时,
逻辑焦点将移动到contextMenu(光标在textBox上不再可见,因此上下文菜单的键工作正常)
但是,当我尝试使用maskedTextBox时,逻辑焦点停留在textBox上,因此ContextMenu没有可用的键
因此,作为一种解决方法,我对您的代码进行了调整,看看这是否有帮助-
<DockPanel Name="DockPanel" Focusable="True" FocusVisualStyle="{x:Null}">
.....
</DockPanel>
更新
由于其窗口窗体文本框的局限性,它不会将键盘焦点放松在上下文菜单打开上
因此,我们必须跟踪蒙面文本框在打开前是否有焦点
上下文菜单,然后在上下文菜单打开后手动设置焦点
关闭
代码示例-
公共主窗口()
{
初始化组件();
InputBindings.Add(
新密钥绑定(
新的RelayCommand(OpenContextMenu),
新的按键手势(Key.T,ModifierKeys.Control));
msk.GotFocus+=新事件处理程序(msk_GotFocus);
msk.LostFocus+=新事件处理程序(msk_LostFocus);
}
bool是focusonmaskedtextbox;
void msk_LostFocus(对象发送方,事件参数e)
{
isFocusOnMaskedTextBox=false;
}
void msk_GotFocus(对象发送方,事件参数e)
{
isFocusOnMaskedTextBox=true;
}
void OpenContextMenu(对象参数)
{
bool moveFocusOnClose=isFocusOnMaskedTextBox;
RoutedEventHandler eventHandler=null;
eventHandler=(s,e)=>
{
if(moveFocusOnClose)
msk.Focus();
DockPanel.ContextMenu.Closed-=eventHandler;
};
if(moveFocusOnClose)
{
键盘。焦点(DockPanel);
}
DockPanel.ContextMenu.IsOpen=true;
DockPanel.ContextMenu.Closed+=eventHandler;
}
谢谢你的回答。这一解决方法大大有助于避免问题。然而,这并不完美,因为上下文菜单关闭后焦点将不会返回文本框。我想你必须对此进行修改,有点像我在回答中所做的。因为Winforms控件没有单独的逻辑和键盘焦点。我在示例应用程序中试用过,效果很好。
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
InputBindings.Add(
new KeyBinding(
new RelayCommand(OpenContextMenu),
new KeyGesture(Key.T, ModifierKeys.Control)));
}
void OpenContextMenu()
{
DockPanel.ContextMenu.PlacementTarget = DockPanel;
DockPanel.ContextMenu.Placement = PlacementMode.Center;
DockPanel.ContextMenu.IsOpen = true;
}
}
<DockPanel Name="DockPanel" Focusable="True" FocusVisualStyle="{x:Null}">
.....
</DockPanel>
void OpenContextMenu(object param)
{
Keyboard.Focus(DockPanel);
DockPanel.ContextMenu.PlacementTarget = DockPanel;
DockPanel.ContextMenu.Placement = PlacementMode.Center;
DockPanel.ContextMenu.IsOpen = true;
}
<DockPanel Name="DockPanel" Focusable="True" FocusVisualStyle="{x:Null}">
<DockPanel.ContextMenu>
<ContextMenu>
<MenuItem Header="aaa"/>
<MenuItem Header="bbb"/>
</ContextMenu>
</DockPanel.ContextMenu>
<StackPanel>
<TextBox x:Name="txt"/>
<WindowsFormsHost>
<wf:MaskedTextBox x:Name="msk"/>
</WindowsFormsHost>
</StackPanel>
</DockPanel>
public MainWindow()
{
InitializeComponent();
InputBindings.Add(
new KeyBinding(
new RelayCommand<object>(OpenContextMenu),
new KeyGesture(Key.T, ModifierKeys.Control)));
msk.GotFocus += new EventHandler(msk_GotFocus);
msk.LostFocus += new EventHandler(msk_LostFocus);
}
bool isFocusOnMaskedTextBox;
void msk_LostFocus(object sender, EventArgs e)
{
isFocusOnMaskedTextBox = false;
}
void msk_GotFocus(object sender, EventArgs e)
{
isFocusOnMaskedTextBox = true;
}
void OpenContextMenu(object param)
{
bool moveFocusOnClose = isFocusOnMaskedTextBox;
RoutedEventHandler eventHandler = null;
eventHandler = (s, e) =>
{
if (moveFocusOnClose)
msk.Focus();
DockPanel.ContextMenu.Closed -= eventHandler;
};
if (moveFocusOnClose)
{
Keyboard.Focus(DockPanel);
}
DockPanel.ContextMenu.IsOpen = true;
DockPanel.ContextMenu.Closed += eventHandler;
}