问题概述
任何KeyBinding
定义的级别高于TextBox
(未指定修改键),都会阻止用户在TextBox
内键入这些键。
最小XAML层次结构:
<Window>
<UserControl>
<Border>
<UserControl>
<TextBox>
最小命令/键绑定:
<UserControl.Resources>
<RoutedUICommand x:Key="Commands.SomeCommand" />
</UserControl.Resources>
<UserControl.InputBindings>
<KeyBinding Key="A" Command="{StaticResource Commands.SomeCommand} />
</UserControl.InputBindings>
<UserControl.CommandBindings>
<CommandBinding Command="{StaticResource Commands.SomeCommand}" Executed="..." />
</UserControl.CommandBindings>
Command
和KeyBinding
是在第一个 UserControl
级别定义的。因此,在此示例中,在文本框中,用户可以自由键入,直到他们按下A
键,然后它就不会将字母插入文本框中。当您按下TextBox.KeyDown
键(和TextBox.PreviewKeyDown
)时,我可以清楚地看到A
和Handled = false
被触发,但这封信不会添加到文本框的文本中,TextBox.PreviewTextInput
执行不。
我正在寻找任何建议,这些建议可能表明什么是吞咽按键并阻止它被TextBox处理,或者与我如何调试此问题有关。
编辑:
感谢Snoop,我能够清楚地看到问题。
TextBox.PreviewKeyDown
隧道向下并通过可视树触发,从Window开始,到TextBox结束TextBox.KeyDown
气泡从TextBox开始向窗口方向返回TextBox.KeyDown
通过第一个设置了KeyBinding的UserControl将Handled设置为true。TextBox.PreviewTextInput
永远不会触发,文本框也不处理输入,因为KeyDown事件设置为已处理。这仍然存在问题,如果文本框具有焦点,如何阻止UserControl处理输入?在Command执行中,我可以检查文本框是否具有键盘焦点,但此时已经太晚了。
答案 0 :(得分:2)
我有同样的问题。 我看了一下key bindind的文档,并且有一个描述,你绑定的键不应该只是键,而是关键的手势,所以它应该是
当然,它只适用于A,但总的来说这是不好的做法。您应该考虑实施一些后面提到的可能性。更多https://msdn.microsoft.com/cs-cz/library/system.windows.input.keybinding(v=vs.110).aspx
答案 1 :(得分:0)
TextInput
和PreviewTextInput
仅在文本实际更改/可能更改时触发。
当您更新要反映的问题时,Command
会拦截事件,并且永远不会引发(预览)TextInput事件。
最好的解决方案是为你的KeyBinding添加一个修饰键,但我怀疑这不是你喜欢的方式。
另一个选项是e.Handle
TextBox上的PreviewKeyDown事件,并使用类似的东西自己引发TextComposition事件:
target.RaiseEvent(new TextCompositionEventArgs(InputManager.Current.PrimaryKeyboardDevice,
new TextComposition(InputManager.Current, target, "A"))
{
RoutedEvent = TextCompositionManager.TextInputEvent
});
(或者,在正确的textBox.Text
)
CaretIndex
说实话,它仍然是一个黑客。
答案 2 :(得分:-1)
只要您使用KeyBinding
,就不会在没有重大黑客攻击的情况下起作用。为此,我实现了一个解决方案:
KeyDown
事件捕获被按下的键(而不是KeyBindings
)。这将在代码的后面,然后从那里打开按下的键以调用所需的命令(在您的情况下为SomeCommand
)。TextBox
正在获取输入,但是您的键绑定命令也在触发。在后面的代码中,检查keyEventArgs.InputSource
的类型,如果它是TextBox
,则忽略按键。它应该像这样:
private void OnKeyDown(object sender, KeyEventArgs e)
{
ICommand command = null;
switch (e.Key)
{
case Key.A:
command = Commands.SomeCommand;
break;
case Key.B:
command = Commands.SomeOtherCommand;
break;
}
bool isSourceATextBox = e.InputSource.GetType() == typeof(TextBox);
if (command != null && !isSourceATextBox)
{
command.Execute(parameter:null);
}
}