如何恢复Outlook VSTO插件中WPF MaterialDesign DialogContent的输入焦点
这个问题是WPF控件在非WPF宿主(比如Outlook VSTO、WinForm宿主)中常见的Win32焦点与WPF键盘路由不同步问题,根源是切换到外部窗口后,Win32层面的活动窗口没有切回WPF控件所在的任务窗格窗口,导致键盘消息被定向到之前的活动窗口,仅修改WPF内部的焦点状态无效。
可按以下步骤依次尝试修复:
步骤1:引入Win32 API声明
首先在你的WPF控件的后台代码类中添加Win32 API导入:
[DllImport("user32.dll")] private static extern bool SetForegroundWindow(IntPtr hWnd);
步骤2:绑定Dialog内容控件的鼠标点击事件
给你的DialogContentControl添加PreviewMouseDown事件绑定,事件处理逻辑如下:
private void DialogContentControl_PreviewMouseDown(object sender, MouseButtonEventArgs e) { // 获取当前WPF控件绑定的Win32窗口句柄源 var hwndSource = HwndSource.FromVisual(sender as Visual) as HwndSource; if (hwndSource == null) return; // 先将Win32层面的活动窗口切到当前WPF控件所在窗口 SetForegroundWindow(hwndSource.Handle); // 同步WPF输入上下文的焦点状态 hwndSource.DocumentInput?.KeyboardFocus?.Navigate(new TraversalRequest(FocusNavigationDirection.First)); // 给当前点击的控件设置焦点 if (e.OriginalSource is UIElement targetElement) { targetElement.Focus(); Keyboard.Focus(targetElement); e.Handled = true; } }
步骤3:调整DialogHost的XAML配置
在materialDesign:DialogHost节点上补充以下焦点相关属性,优化WPF内部的焦点路由:
<materialDesign:DialogHost Focusable="True" IsTabStop="True" KeyboardNavigation.TabNavigation="Cycle" KeyboardNavigation.ControlTabNavigation="Local" <!-- 保留你原来的其他属性配置 --> > <!-- 你原来的DialogContent配置不变 --> <materialDesign:DialogHost.DialogContent> <ContentControl x:Name="DialogContentControl" ContentTemplateSelector="{StaticResource DTSDialogObject}" Focusable="True" Content="{Binding DialogViewModel, UpdateSourceTrigger=PropertyChanged, Mode=OneWay}" HorizontalAlignment="Center" Width="300" VerticalAlignment="Center" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" /> </materialDesign:DialogHost.DialogContent> </materialDesign:DialogHost>
可选补充方案
如果弹窗打开时就需要默认定位到第一个输入框,可在DialogViewModel赋值后调用以下逻辑,延迟设置焦点避免视觉树未渲染导致的设置失效:
Dispatcher.BeginInvoke(DispatcherPriority.Input, new Action(() => { // 自己实现FindChild扩展方法查找弹窗内第一个可输入的文本框 var firstInput = DialogContentControl.FindChild<TextBox>(); if (firstInput != null) { firstInput.Focus(); Keyboard.Focus(firstInput); } }));
内容的提问来源于stack exchange,提问作者buks
相关产品推荐
相关产品推荐

