Ral*_*ine 22 wpf xaml focus mvvm inputbinding
以下情况.我有一个带有五个键绑定的UserControl.当TextBox具有焦点时,UserControl的键绑定将停止触发..
有没有办法解决这个'问题'?
<UserControl.InputBindings>
<KeyBinding Key="PageDown" Modifiers="Control" Command="{Binding NextCommand}"></KeyBinding>
<KeyBinding Key="PageUp" Modifiers="Control" Command="{Binding PreviousCommand}"></KeyBinding>
<KeyBinding Key="End" Modifiers="Control" Command="{Binding LastCommand}"></KeyBinding>
<KeyBinding Key="Home" Modifiers="Control" Command="{Binding FirstCommand}"></KeyBinding>
<KeyBinding Key="F" Modifiers="Control" Command="{Binding SetFocusCommand}"></KeyBinding>
</UserControl.InputBindings>
<TextBox Text="{Binding FilterText, UpdateSourceTrigger=PropertyChanged}">
<TextBox.InputBindings>
<KeyBinding Gesture="Enter" Command="{Binding RelativeSource={RelativeSource AncestorType={x:Type UserControl }}, Path=DataContext.FilterCommand}"></KeyBinding>
</TextBox.InputBindings>
</TextBox>
Run Code Online (Sandbox Code Playgroud)
似乎功能键(F1等)和ALT+ [key]工作.我假设CTRL和SHIFT修饰符以某种方式"阻止"事件冒泡到UserControl.
Adi*_*ter 48
一些输入绑定有效的原因,有些则不是TextBox控件捕获并处理一些键绑定.例如,它处理CTRL+ V用于粘贴,CTRL+ Home用于转到文本的开头等.另一方面,其他键组合(如CTRL+)F3不由TextBox处理,因此它们将冒泡.
如果您只是想禁用TextBox的输入绑定,那么这很简单 - 您可以使用该ApplicationCommands.NotACommand命令来禁用默认行为.例如,在以下情况下,将禁用使用CTRL+ 粘贴V:
<TextBox>
<TextBox.InputBindings>
<KeyBinding Key="V" Modifiers="Control" Command="ApplicationCommands.NotACommand" />
</TextBox.InputBindings>
</TextBox>
Run Code Online (Sandbox Code Playgroud)
然而,让它冒泡到用户控件有点棘手.我的建议是创建一个附加行为,该行为将应用于UserControl,注册到其PreviewKeyDown事件,并在到达TextBox之前根据需要执行其输入绑定.执行输入绑定时,这将优先于UserControl.
我写了一个基本的行为,实现了这个功能,让你开始:
public class InputBindingsBehavior
{
public static readonly DependencyProperty TakesInputBindingPrecedenceProperty =
DependencyProperty.RegisterAttached("TakesInputBindingPrecedence", typeof(bool), typeof(InputBindingsBehavior), new UIPropertyMetadata(false, OnTakesInputBindingPrecedenceChanged));
public static bool GetTakesInputBindingPrecedence(UIElement obj)
{
return (bool)obj.GetValue(TakesInputBindingPrecedenceProperty);
}
public static void SetTakesInputBindingPrecedence(UIElement obj, bool value)
{
obj.SetValue(TakesInputBindingPrecedenceProperty, value);
}
private static void OnTakesInputBindingPrecedenceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((UIElement)d).PreviewKeyDown += new KeyEventHandler(InputBindingsBehavior_PreviewKeyDown);
}
private static void InputBindingsBehavior_PreviewKeyDown(object sender, KeyEventArgs e)
{
var uielement = (UIElement)sender;
var foundBinding = uielement.InputBindings
.OfType<KeyBinding>()
.FirstOrDefault(kb => kb.Key == e.Key && kb.Modifiers == e.KeyboardDevice.Modifiers);
if (foundBinding != null)
{
e.Handled = true;
if (foundBinding.Command.CanExecute(foundBinding.CommandParameter))
{
foundBinding.Command.Execute(foundBinding.CommandParameter);
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
用法:
<UserControl local:InputBindingsBehavior.TakesInputBindingPrecedence="True">
<UserControl.InputBindings>
<KeyBinding Key="Home" Modifiers="Control" Command="{Binding MyCommand}" />
</UserControl.InputBindings>
<TextBox ... />
</UserControl>
Run Code Online (Sandbox Code Playgroud)
希望这可以帮助.
小智 5
阿迪·莱斯特的解决方案效果很好。这是使用行为的类似解决方案。C# 代码:
public class AcceptKeyBinding : Behavior<UIElement>
{
private TextBox _textBox;
/// <summary>
/// Subscribes to the PreviewKeyDown event of the <see cref="TextBox"/>.
/// </summary>
protected override void OnAttached()
{
base.OnAttached();
_textBox = AssociatedObject as TextBox;
if (_textBox == null)
{
return;
}
_textBox.PreviewKeyDown += TextBoxOnPreviewKeyDown;
}
private void TextBoxOnPreviewKeyDown(object sender, KeyEventArgs keyEventArgs)
{
var uielement = (UIElement)sender;
var foundBinding = uielement.InputBindings
.OfType<KeyBinding>()
.FirstOrDefault(kb => kb.Key == keyEventArgs.Key && kb.Modifiers == keyEventArgs.KeyboardDevice.Modifiers);
if (foundBinding != null)
{
keyEventArgs.Handled = true;
if (foundBinding.Command.CanExecute(foundBinding.CommandParameter))
{
foundBinding.Command.Execute(foundBinding.CommandParameter);
}
}
}
/// <summary>
/// Unsubscribes to the PreviewKeyDown event of the <see cref="TextBox"/>.
/// </summary>
protected override void OnDetaching()
{
if (_textBox == null)
{
return;
}
_textBox.PreviewKeyDown -= TextBoxOnPreviewKeyDown;
base.OnDetaching();
}
}
Run Code Online (Sandbox Code Playgroud)
以及 XAML:
<TextBox>
<TextBox.InputBindings>
<KeyBinding Key="Enter" Modifiers="Shift" Command="{Binding CommandManager[ExecuteCommand]}"
CommandParameter="{Binding ExecuteText}" />
</TextBox.InputBindings>
<i:Interaction.Behaviors>
<behaviours:AcceptKeyBinding />
</i:Interaction.Behaviors>
</TextBox>
Run Code Online (Sandbox Code Playgroud)
小智 5
除了阿迪·莱斯特(Adi Lester)的(非常有帮助的)回答之外,我还想建议一些有助于我实施的改进/扩展。
手势匹配
也可以通过调用Gesture.Matches 来完成foundBinding。将foundBinding Linq 查询更改为以下内容:
KeyBinding foundBinding = ((UIElement)this).InputBindings
.OfType<KeyBinding>()
.FirstOrDefault(inputBinding => inputBinding.Gesture.Matches(sender, eventArgs));
Run Code Online (Sandbox Code Playgroud)
鼠标绑定
此外,您还可以定义 MouseBindings。
<MouseBinding Command="{Binding DataContext.AddInputValueCommand, ElementName=root}" CommandParameter="{Binding}" Gesture="Shift+MiddleClick" />
Run Code Online (Sandbox Code Playgroud)
然后,您还需要订阅 PreviewMouseEvents,例如 PreviewMouseUp 和 PreviewMouseDoubleClick。其实现与 KeyBindings 几乎相同。
private void OnTextBoxPreviewMouseUp(object sender, MouseButtonEventArgs eventArgs)
{
MouseBinding foundBinding = ((UIElement)this).InputBindings
.OfType<MouseBinding>()
.FirstOrDefault(inputBinding => inputBinding.Gesture.Matches(sender, eventArgs));
if (foundBinding != null)
{
eventArgs.Handled = true;
if (foundBinding.Command.CanExecute(foundBinding.CommandParameter))
{
foundBinding.Command.Execute(foundBinding.CommandParameter);
}
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
22260 次 |
| 最近记录: |