我已经编写了一个自定义的OnScreen键盘作为UserControl,可以更好地控制用户可以键入的内容(字母数字/ Numpad /导航键 - 类似的东西),并在设计时更好地控制屏幕布局。
OSK通过操纵文本框控件的文本和选择属性/功能来工作。
我的主要问题是如何找到合适的TextBox来注入文本。
我的第一个天真的方法是手动注册我想要与OSK控件一起使用的每个TextBox,并使用那些注册TextBox的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将按下的键直接注入其中。在我的Page的构造函数中也包含OSK控件,我会调用RegisterInput()
,并引用我在页面上定义的每个TextBox。这很好 - 如果我有这些参考。
但现在我正在使用UserControls。这也删除了TextBoxes无法直接引用,但我可以在InitializeComponent()
之后编写某种VisualTree-Scan来查找所有引用,并在我找到的每个引用上调用RegisterInput()
。如果我只需要这样做一次,这不是问题(尽管它仍然很难看。)
更进一步 - ListBoxes具有动态更改内容和DataTemplates。现在每次发生变化时我都需要显式重新扫描整个VisualTree。但是如何检测这些变化?
问题是:我可以在我的VisualTree中的任何元素得到/失去焦点时获得一个事件,而不事先知道所有这些元素(从而完全替换RegisterInput()
)?或者我可以听取对VisualTree的更改以重新扫描所有控件,然后为我找到的每个TextBox手动调用RegisterInput()
吗?
目标是每次在UI中的任何TextBox / Control上引发GetFocus / LostFocus事件时调用处理程序,以便我可以更新键盘以显示全尺寸字母数字键盘(对于默认文本框)或者缩短了numpad(例如,对于绑定到数字后备字段的文本框)。
或者:还有其他方法可以在选定的文本框更改后立即注入文字和调用UpdateKeyboardMode()
来更新键盘布局吗?
我想到的其他选项包括:
构建一个从TextBox派生的自定义控件,让它自己注册到OSK。如果我找不到更好的方法,我可能会采用这种方法。但是这会破坏对我的控件不存在的第三方库的支持,因此不会使用“支持osk的特殊魔法文本框”。
根本不要使用事件。一旦用户按下OSK上的键并将文本注入到焦点实例中,就可以使用FocusManager获取当前聚焦的TextBox。这种方法的问题是,它完全破坏了使OSK适应不同输入类型的能力(字母数字与仅Numpad),因为在按键之前我无法确定我需要的键盘类型。
使用计时器重新扫描VisualTree。不会这样做,那太过分了。
使用Win10 IoT提供的OnScreen-Keyboard。两个问题:它没有设计时支持并且显示在元素上方,即使聚焦元素直接位于键盘下方(如果需要也可以接受),但我不知道如何在完整之间更改键盘“布局”大小的字母数字键盘和缩短的Numpad,只包含数字和一些键。此外,它不允许使用自定义键(例如,箭头键用于导航,自定义返回键处理)。
答案 0 :(得分:0)
在聊天论坛中讨论后,实际问题不是创建Custom OSK
控件并使用它来与TextBoxs
交互,而是“绑定使用自定义控件”在textbox
处包裹OSK
需要显示Custom OSK
。
解决方案是监听OS-OSK事件,当它们被触发时,弹出Textbox
这种方式你不必将$resource
包装在用户控件中并使用在整个项目中。