How to rewrite WPF routed commands dispatching mechanism

跟風遠走 提交于 2019-12-10 19:29:54

问题


Can I extend WPF commands routing in a way so it would first check whether command can be invoked in the focused field and if not in some other (never changing)? Is there any hooks for that? Maybe you don't know whether that would work but saw something similar somewhere on the net and can spare the link?

Abstract example

For example if I would be writing a text editor with a side panel and panel would have the focus. If I would press Ctrl+G some command will be invoked because panel has command binding and focus (that normal WPF behavior). Also if I press Ctrl+H but this time panel have no command binding for invoked command. In this case I would want routing engine to switch to text editor and bubble same command there to.

Real example

I have a menu item which says Paste but focus is on the side panel. If I press menu command binded to panel will be executed. Suppose there is no appropriate command binded to panel. In this case I would like to paste into text editor.

Code

This code more or less represents this scenario. I would like to press Ctrl+H and execute CommandBinding_Executed_1

Window1.xaml

<Window x:Class="WpfApplication1.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:WpfApplication1">
    <StackPanel>        
        <TextBox x:Name="textBlock1">
            <TextBox.CommandBindings>
                <CommandBinding Command="local:Window1.TestCommand" Executed="CommandBinding_Executed_1" />
                <CommandBinding Command="local:Window1.ForwardedTestCommand" Executed="CommandBinding_Executed_1" />
            </TextBox.CommandBindings>
        </TextBox>
        <TextBox x:Name="textBlock2">
            <TextBox.CommandBindings>
                <CommandBinding Command="local:Window1.TestCommand" Executed="CommandBinding_Executed_2" />
            </TextBox.CommandBindings>
            <TextBox.InputBindings>
                <KeyBinding Command="local:Window1.TestCommand" Gesture="Ctrl+G" />
                <KeyBinding Command="local:Window1.ForwardedTestCommand" Gesture="Ctrl+H" />
            </TextBox.InputBindings>
        </TextBox>
    </StackPanel>
</Window>

Window1.xaml.cs

using System.Windows;
using System.Windows.Input;

namespace WpfApplication1
{
    public partial class Window1 : Window
    {
        public static RoutedUICommand TestCommand = new RoutedUICommand("TestCommand", "TestCommand", typeof(Window1));
        public static RoutedUICommand ForwardedTestCommand = new RoutedUICommand("ForwardedTestCommand", "ForwardedTestCommand", typeof(Window1));

        public Window1()
        {
            InitializeComponent();
        }

        private void CommandBinding_Executed_1(object sender, ExecutedRoutedEventArgs e)
        {
            MessageBox.Show("CommandBinding_Executed_1");
        }

        private void CommandBinding_Executed_2(object sender, ExecutedRoutedEventArgs e)
        {
            MessageBox.Show("CommandBinding_Executed_2");
        }
    }
}

回答1:


The way I was able to solve this is using Window.AddHandler method to catch all routed command events and then re-raise them from textBlock1 like so.

textBlock1.RaiseEvent(e);

I don't have a code for that yet, but the idea is that routed event if not handled is bubbled up to window scope where we catch all unhandled events and re-raise them from main window area



来源:https://stackoverflow.com/questions/989542/how-to-rewrite-wpf-routed-commands-dispatching-mechanism

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!