如何将快捷方式从 MainWindow 传递到 ContentControl 中的 UserControl?

How to pass shortcuts from MainWindow to the UserControl in ContentControl?

在我的 Window 中动态加载到 ContentControl 的 UserControl 不接收在 UserControl XAML 内部定义的键盘快捷键,以防它没有获得焦点。

我需要在不聚焦 UserControl 的情况下为动态加载的 UserControl 实现键盘快捷键。

我无法在 MainWindow 上定义 InputBindings,因为 InputBindigs 的变化取决于当前加载的 UserControl。

1) 所以我尝试通过 RaiseEvent 将所有 Window_KeyUp 发送到加载的 UserControl,但没有成功。 (Whosebug 异常或未调用任何操作)

2) 当 UserControl 已加载到 ContentControl 时,我还尝试通过 LoadedUserControl.InputBindings 填充 MainWindow.InputBindings... 运气不好(定义的命令在上下文中未知)

UserControl.xaml
----------------

<UserControl.InputBindings>
        <KeyBinding Key="N" Command="{Binding Path=NewOrderCommand}" Modifiers="Control" />
</UserControl.InputBindings>

如果 UserControl 获得焦点,这将起作用。

所以为了摆脱焦点,我尝试了这个:

MainWindow.xaml.cs
-------------------

private void MainWindow_KeyUp(object sender, System.Windows.Input.KeyEventArgs e)
{
    // ModulePanel points to the loaded UserControl
    ViewModel.CurrentModule.ModulePanel.RaiseEvent(e);
    e.Handled = true;
}

所以这发出了 WhosebugException

我试过设置e.Handled = true;在 RaiseEvent(e) 之前,但它不会将事件传递给 UserControl - 所以什么也没有发生;

我还尝试将 InputBindings 从 UserControl 获取到 MainWindow:

foreach(InputBinding bi in UserControl.InputBindings)
   MainWindow.InputBindings.Add(bi);

但我在调试中遇到异常 window:

找不到目标元素的管理 FrameworkElement 或 FrameworkContentElement。 BindingExpression:Path=新订单命令;数据项=空;目标元素是 'KeyBinding' (HashCode=35527846);目标 属性 是 'Command'(类型 'ICommand')

我的期望是,我将动态更改 Window InputBindings 取决于加载的 UserControl,其中定义了 InputBindings。

尝试将 ViewModel 用作 DataContext,并让它们使用 Messenger 相互通信。您可以将所需的信息发送到未获得焦点的 Usercontrol 的 ViewModel。

如果您想坚持使用代码隐藏,请订阅 Mainwindow 上的事件处理程序:

PreviewKeyUp += userCtrl.OnKeyUp;

并在您的用户控件中处理它

public void OnKeyUp(object sender, KeyEventArgs e)
    {
        MyTextBlock.Text = e.Key.ToString();
    }

如果您希望 UserControl 能够处理 window 中的所有按键操作,您可以使用 Window.GetWindow 获取对父 window 的引用一旦 UserControl 被加载,然后将事件处理程序连接到它:

public partial class UserControl1 : UserControl
{
    public UserControl1()
    {
        InitializeComponent();
        Loaded += (s, e) =>
        {
            Window parentWindow = Window.GetWindow(this);
            parentWindow.PreviewKeyDown += ParentWindow_PreviewKeyDown;
        };
        Unloaded += (s, e) =>
        {
            Window parentWindow = Window.GetWindow(this);
            parentWindow.PreviewKeyDown -= ParentWindow_PreviewKeyDown;

        };
    }

    private void ParentWindow_PreviewKeyDown(object sender, KeyEventArgs e)
    {
        //do something...
    }
}