自定义 OSK:收听 TextBox 焦点
Custom OSK: Listen to TextBox Focus
我已经编写了一个自定义屏幕键盘作为用户控件,以便更好地控制用户可以输入的内容(Alphanumeric/Numpad/Navigation 键 - 类似的东西)并在设计时更好地控制屏幕布局时间.
OSK 通过操纵文本框控件的文本和 selection-properties/functions 来工作。
我的主要问题是如何找到正确的文本框来插入文本。
我的第一个天真的方法是手动注册我想使用 OSK 控件的每个文本框,并使用这些已注册文本框的 GotFocus/LostFocus 来确定活动控件:
public void RegisterInput(TextBox text) {
if (!_listeners.ContainsKey(text)) {
_listeners.Add(text, modes);
text.GotFocus += Input_OnGotFocus;
text.LostFocus += Input_OnLostFocus;
}
}
private void Input_OnLostFocus(object sender, RoutedEventArgs routedEventArgs) {
if (_focused == sender) {
_focused = null;
IsEnabled = false;
UpdateKeyboardMode(); // << Updates Keyboard layout (Alphanumerical vs Numpad) based on focused control
}
}
private void Input_OnGotFocus(object sender, RoutedEventArgs routedEventArgs) {
_focused = (TextBox) sender;
IsEnabled = true;
UpdateKeyboardMode();
Bindings.Update();
}
我在这里使用 Focus,因为我需要确定为每个 TextBox 显示哪种键盘(全尺寸字母数字键盘还是短小键盘)。然后使用 _focused
TextBox 将按下的键直接注入其中。在我的页面的构造函数中,它也包含 OSK 控件,我将调用 RegisterInput()
并引用我在页面上定义的每个文本框。这很好用——如果我有这些参考资料的话。
但现在我正在使用 UserControls。这也删除了无法直接引用的文本框,但我可以在 InitializeComponent()
之后编写某种 VisualTree-Scan 以查找所有引用并在我找到的每个引用上调用 RegisterInput()
。如果我只需要这样做一次,这不是问题(虽然它仍然很难看)。
更进一步 - 具有动态更改内容和数据模板的列表框。现在我需要在每次发生变化时明确地重新扫描整个 VisualTree。但是如何检测这些变化呢?
问题是: 我能否在我的 VisualTree gets/looses 中的 $any 元素获得焦点时立即获得事件,而无需事先知道所有这些元素(因此替换 RegisterInput()
完全)?或者我可以听取对 VisualTree 的更改以重新扫描所有控件,然后为我找到的每个 TextBox 手动调用 RegisterInput()
吗?
目标是在每次引发 UI 中任何 TextBox/Control 上的 GetFocus/LostFocus 事件时调用一个处理程序,以便我可以更新键盘以显示完整的-大小的字母数字键盘(用于默认文本框)或缩短的数字键盘(例如,用于绑定到数字支持字段的文本框)。
或者:有没有其他方法可以插入文本和调用UpdateKeyboardMode()
尽快更新键盘布局选定的文本框发生变化?
我考虑的其他选项包括:
构建一个派生自 TextBox 的自定义控件,并让它自己注册到 OSK。如果找不到更好的方法,我可能会采用这种方法。但这将破坏对第 3 方库的支持,其中不存在我的控件,因此不使用 "special magical textbox with osk support".
根本不使用事件。用户在我的 OSK 上按下一个键后,立即使用 FocusManager 获取当前聚焦的 TextBox 并将文本注入聚焦实例。这种方法的问题是,它完全破坏了使 OSK 适应不同输入类型(字母数字与仅数字键盘)的能力,因为我无法在按下键之前确定我需要的键盘类型。
使用计时器重新扫描 VisualTree。不会那样做,那太过分了。
使用 Win10 IoT 提供的屏幕键盘。两个问题:它没有设计时支持并且显示在元素上方,即使焦点元素直接位于键盘下方(如果需要,可以接受),但我不知道如何在全尺寸字母数字键盘和一个缩短的数字键盘,它只包含数字和一些键。它也不允许使用自定义键(例如用于导航的箭头键,自定义 return 键处理)。
在聊天论坛讨论后,实际问题不是创建 Custom OSK
控件并使用它与 TextBoxs
交互,而是 "being bound to use custom control" 包装a textbox
需要显示 OSK
的所有地方。
解决方案是监听 OS-OSK 事件,当它们被触发时,弹出 Custom OSK
这样你就不必将 Textbox
包装在用户控制并在整个项目中使用它。
我已经编写了一个自定义屏幕键盘作为用户控件,以便更好地控制用户可以输入的内容(Alphanumeric/Numpad/Navigation 键 - 类似的东西)并在设计时更好地控制屏幕布局时间.
OSK 通过操纵文本框控件的文本和 selection-properties/functions 来工作。
我的主要问题是如何找到正确的文本框来插入文本。
我的第一个天真的方法是手动注册我想使用 OSK 控件的每个文本框,并使用这些已注册文本框的 GotFocus/LostFocus 来确定活动控件:
public void RegisterInput(TextBox text) {
if (!_listeners.ContainsKey(text)) {
_listeners.Add(text, modes);
text.GotFocus += Input_OnGotFocus;
text.LostFocus += Input_OnLostFocus;
}
}
private void Input_OnLostFocus(object sender, RoutedEventArgs routedEventArgs) {
if (_focused == sender) {
_focused = null;
IsEnabled = false;
UpdateKeyboardMode(); // << Updates Keyboard layout (Alphanumerical vs Numpad) based on focused control
}
}
private void Input_OnGotFocus(object sender, RoutedEventArgs routedEventArgs) {
_focused = (TextBox) sender;
IsEnabled = true;
UpdateKeyboardMode();
Bindings.Update();
}
我在这里使用 Focus,因为我需要确定为每个 TextBox 显示哪种键盘(全尺寸字母数字键盘还是短小键盘)。然后使用 _focused
TextBox 将按下的键直接注入其中。在我的页面的构造函数中,它也包含 OSK 控件,我将调用 RegisterInput()
并引用我在页面上定义的每个文本框。这很好用——如果我有这些参考资料的话。
但现在我正在使用 UserControls。这也删除了无法直接引用的文本框,但我可以在 InitializeComponent()
之后编写某种 VisualTree-Scan 以查找所有引用并在我找到的每个引用上调用 RegisterInput()
。如果我只需要这样做一次,这不是问题(虽然它仍然很难看)。
更进一步 - 具有动态更改内容和数据模板的列表框。现在我需要在每次发生变化时明确地重新扫描整个 VisualTree。但是如何检测这些变化呢?
问题是: 我能否在我的 VisualTree gets/looses 中的 $any 元素获得焦点时立即获得事件,而无需事先知道所有这些元素(因此替换 RegisterInput()
完全)?或者我可以听取对 VisualTree 的更改以重新扫描所有控件,然后为我找到的每个 TextBox 手动调用 RegisterInput()
吗?
目标是在每次引发 UI 中任何 TextBox/Control 上的 GetFocus/LostFocus 事件时调用一个处理程序,以便我可以更新键盘以显示完整的-大小的字母数字键盘(用于默认文本框)或缩短的数字键盘(例如,用于绑定到数字支持字段的文本框)。
或者:有没有其他方法可以插入文本和调用UpdateKeyboardMode()
尽快更新键盘布局选定的文本框发生变化?
我考虑的其他选项包括:
构建一个派生自 TextBox 的自定义控件,并让它自己注册到 OSK。如果找不到更好的方法,我可能会采用这种方法。但这将破坏对第 3 方库的支持,其中不存在我的控件,因此不使用 "special magical textbox with osk support".
根本不使用事件。用户在我的 OSK 上按下一个键后,立即使用 FocusManager 获取当前聚焦的 TextBox 并将文本注入聚焦实例。这种方法的问题是,它完全破坏了使 OSK 适应不同输入类型(字母数字与仅数字键盘)的能力,因为我无法在按下键之前确定我需要的键盘类型。
使用计时器重新扫描 VisualTree。不会那样做,那太过分了。
使用 Win10 IoT 提供的屏幕键盘。两个问题:它没有设计时支持并且显示在元素上方,即使焦点元素直接位于键盘下方(如果需要,可以接受),但我不知道如何在全尺寸字母数字键盘和一个缩短的数字键盘,它只包含数字和一些键。它也不允许使用自定义键(例如用于导航的箭头键,自定义 return 键处理)。
在聊天论坛讨论后,实际问题不是创建 Custom OSK
控件并使用它与 TextBoxs
交互,而是 "being bound to use custom control" 包装a textbox
需要显示 OSK
的所有地方。
解决方案是监听 OS-OSK 事件,当它们被触发时,弹出 Custom OSK
这样你就不必将 Textbox
包装在用户控制并在整个项目中使用它。