子控件上的WPF覆盖/重置键绑定
本文关键字:绑定 覆盖 控件 WPF | 更新日期: 2023-09-27 18:26:16
我有一个窗口,上面有绑定到numpad键的命令,如下所示:
<!-- Set keybindings -->
<controls:MetroWindow.InputBindings>
<!-- NumPad Shortcuts for selecting reasons -->
<KeyBinding Key="NumPad0" Command="{Binding OnReasonShortcutKeyPressedCommand}" CommandParameter="0" />
<KeyBinding Key="NumPad1" Command="{Binding OnReasonShortcutKeyPressedCommand}" CommandParameter="1" />
<KeyBinding Key="NumPad2" Command="{Binding OnReasonShortcutKeyPressedCommand}" CommandParameter="2" />
<KeyBinding Key="NumPad3" Command="{Binding OnReasonShortcutKeyPressedCommand}" CommandParameter="3" />
<KeyBinding Key="NumPad4" Command="{Binding OnReasonShortcutKeyPressedCommand}" CommandParameter="4" />
<KeyBinding Key="NumPad5" Command="{Binding OnReasonShortcutKeyPressedCommand}" CommandParameter="5" />
<KeyBinding Key="NumPad6" Command="{Binding OnReasonShortcutKeyPressedCommand}" CommandParameter="6" />
<KeyBinding Key="NumPad7" Command="{Binding OnReasonShortcutKeyPressedCommand}" CommandParameter="7" />
<KeyBinding Key="NumPad8" Command="{Binding OnReasonShortcutKeyPressedCommand}" CommandParameter="8" />
<KeyBinding Key="NumPad9" Command="{Binding OnReasonShortcutKeyPressedCommand}" CommandParameter="9" />
<!-- Others -->
<KeyBinding Key="Back" Command="{Binding OnReasonGoBackClickedCommand}" />
<KeyBinding Key="Escape" Command="{Binding OnEscapeClickedCommand}" />
</controls:MetroWindow.InputBindings>
在后端,这被处理为:
ICommand _onReasonShortcutKeyPressedCommand;
public ICommand OnReasonShortcutKeyPressedCommand
{
get
{
return _onReasonShortcutKeyPressedCommand ??
(_onReasonShortcutKeyPressedCommand = new RelayCommand(OnReasonShortcutKeyPressedCommand_Execute));
}
}
private void OnReasonShortcutKeyPressedCommand_Execute(object param)
{
//Find which key was presses by command param
int keyPressed = Int32.Parse((string)param);
// Do something bla bla bla
}
现在,这个窗口还包含一些必须在其中输入数字的文本框。当然,窗口级别的键绑定会导致触发命令,而不是打印实际数字。有什么我可以推翻的吗?
不确定是否有更好的方法来解决这个问题,但我的建议是使用attach属性来存档这个问题。以下是示例:
在XAML中,您应该将新行为(LimitBindings)附加到TextBox:
XAML:
<TextBox behavs:KeyBindingBehavior.LimitKeyBindings="True"></TextBox>
并创建您的行为类(+Helper方法来获取父窗口-它应该放在其他地方:):
public static class KeyBindingBehavior
{
//to keep window's bindings.
private static InputBindingCollection windowBindings;
public static bool GetLimitKeyBindings(DependencyObject obj)
{
return (bool)obj.GetValue(LimitKeyBindingsProperty);
}
public static void SetLimitKeyBindings(DependencyObject obj, bool value)
{
obj.SetValue(LimitKeyBindingsProperty, value);
}
public static readonly DependencyProperty LimitKeyBindingsProperty =
DependencyProperty.RegisterAttached(
"LimitKeyBindings",
typeof(bool),
typeof(KeyBindingBehavior),
new PropertyMetadata(false, PropertyChangedCallback));
private static void PropertyChangedCallback(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs args)
{
TextBox textBox = dependencyObject as TextBox;
if (textBox != null)
{
textBox.GotKeyboardFocus += textBox_GotKeyboardFocus;
textBox.LostKeyboardFocus += textBox_LostKeyboardFocus;
}
}
static void textBox_LostKeyboardFocus(object sender, System.Windows.Input.KeyboardFocusChangedEventArgs e)
{
var window = GetParentWindow(sender as DependencyObject);
window.InputBindings.AddRange(windowBindings);
}
static void textBox_GotKeyboardFocus(object sender, System.Windows.Input.KeyboardFocusChangedEventArgs e)
{
var window = GetParentWindow(sender as DependencyObject);
windowBindings = new InputBindingCollection(window.InputBindings);
window.InputBindings.Clear();
}
// This helper method should be in seperate class
public static Window GetParentWindow(DependencyObject child)
{
DependencyObject parentObject = VisualTreeHelper.GetParent(child);
if (parentObject == null)
{
return null;
}
Window parent = parentObject as Window;
if (parent != null)
{
return parent;
}
else
{
return GetParentWindow(parentObject);
}
}
}
不要忘记在XAML中添加指向行为类的引用:
xmlns:behavs="clr-namespace:WpfApplication1"