【发布时间】:2019-06-29 20:43:30
【问题描述】:
我有一个带有 WPF 对话框窗口的 VSTO(Excel 或 Word)插件,以模态方式显示。该对话框有一个文本框,我需要首先关注它。我可以使用FocusManager 或Keyboard 类等各种方法或通过请求Traversal 来使其集中。或者我可以通过keybd_event() (user32.dll) 模拟 TAB 按键。
问题在于这些方法中的任何一种,该领域似乎都没有“完全”集中。光标显示在 TextBox 中,但它不闪烁并且无法输入!为了解决这个问题,我可以:
按 TAB 一次(不是以编程方式),光标将开始闪烁,我可以输入;或
按 Alt-Tab 切换到另一个应用程序,然后返回。再次,光标将开始闪烁,我可以输入。
编辑:解决方案
ErrCode 的基本方法可以可靠地工作,但需要进行一些修改。首先,我不是只做一次他的想法,而是在所有窗户上做。其次,我在自己的窗口加载之后打开虚拟窗口,而不是之前。最后,我介绍了一些延迟,否则该方法将无法正常工作:
// Window or UserControl, works for both or any FrameworkElement technically.
public static class FocusExtensions
{
#region FocusElementOnLoaded Attached Behavior
public static IInputElement GetFocusElementOnLoaded(FrameworkElement obj)
{
return (IInputElement)obj.GetValue(FocusElementOnLoadedProperty);
}
public static void SetFocusElementOnLoaded(FrameworkElement obj, IInputElement value)
{
obj.SetValue(FocusElementOnLoadedProperty, value);
}
public static readonly DependencyProperty FocusElementOnLoadedProperty =
DependencyProperty.RegisterAttached("FocusElementOnLoaded", typeof(IInputElement), typeof(FocusExtensions), new PropertyMetadata(null, FocusElementOnLoadedChangedCallback));
private static async void FocusElementOnLoadedChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
// This cast always succeeds.
var c = (FrameworkElement) d;
var element = (IInputElement) e.NewValue;
if (c != null && element != null)
{
if (c.IsLoaded)
await FocusFirst(element);
else
c.Loaded += async (sender, args) =>
await FocusFirst(element);
}
}
private static async Task FocusFirst(IInputElement firstInputElement)
{
var tmpWindow = new Window
{
Width = 0,
Height = 0,
Visibility = Visibility.Collapsed
};
tmpWindow.Loaded += async (s, e) =>
{
await Task.Delay(1);
Application.Current?.Dispatcher?.Invoke(() =>
{
tmpWindow.Close();
firstInputElement.Focus();
});
};
await Task.Delay(1);
Application.Current?.Dispatcher?.Invoke(() =>
{
tmpWindow.ShowDialog();
});
}
#endregion FocusElementOnLoaded Attached Behavior
}
要应用,在 XAML 的用户控件或窗口中,添加:
FocusExtensions.FocusElementOnLoaded="{Binding ElementName=MyTextBox}"
MyTextBox 当然必须派生自IInputElement。
【问题讨论】:
-
您使用哪个代码来显示您的 WPF 对话框窗口?
-
我将所有者设置为 Excel 主窗口,然后只是 .ShowDialog()。
-
我可以看看你使用的完整代码吗?
-
@ChrisBordeman 如果没有minimal reproducible example 来阐明您的具体问题或其他详细信息以准确突出您需要什么,就很难重现问题,从而更好地理解所询问的内容。
-
代码已添加。 XAML 没什么特别的,发生在所有窗口上。