自定义OSK:收听TextBox Focus

时间:2018-02-18 15:16:13

标签: c# uwp windows-10-iot-core

我已经编写了一个自定义的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()来更新键盘布局吗?

我想到的其他选项包括:

  1. 构建一个从TextBox派生的自定义控件,让它自己注册到OSK。如果我找不到更好的方法,我可能会采用这种方法。但是这会破坏对我的控件不存在的第三方库的支持,因此不会使用“支持osk的特殊魔法文本框”。

  2. 根本不要使用事件。一旦用户按下OSK上的键并将文本注入到焦点实例中,就可以使用FocusManager获取当前聚焦的TextBox。这种方法的问题是,它完全破坏了使OSK适应不同输入类型的能力(字母数字与仅Numpad),因为在按键之前我无法确定我需要的键盘类型。

  3. 使用计时器重新扫描VisualTree。不会这样做,那太过分了。

  4. 使用Win10 IoT提供的OnScreen-Keyboard。两个问题:它没有设计时支持并且显示在元素上方,即使聚焦元素直接位于键盘下方(如果需要也可以接受),但我不知道如何在完整之间更改键盘“布局”大小的字母数字键盘和缩短的Numpad,只包含数字和一些键。此外,它不允许使用自定义键(例如,箭头键用于导航,自定义返回键处理)。

1 个答案:

答案 0 :(得分:0)

在聊天论坛中讨论后,实际问题不是创建Custom OSK控件并使用它来与TextBoxs交互,而是“绑定使用自定义控件”在textbox处包裹OSK需要显示Custom OSK

解决方案是监听OS-OSK事件,当它们被触发时,弹出Textbox这种方式你不必将$resource包装在用户控件中并使用在整个项目中。

指向文档的链接: - respond to the presence of the touch keyboard