如何重写WPF路由命令调度机制

时间:2009-06-12 23:57:35

标签: wpf routed-commands

我是否可以以某种方式扩展WPF命令路由,以便首先检查是否可以在聚焦字段中调用命令,如果不在其他字段中调用(从不更改)?那有什么钩子吗?也许你不知道这是否会起作用,但在网上的某个地方看到类似的东西并且可以省去链接?

抽象示例

例如,如果我要编写带有侧面板的文本编辑器,面板就会有焦点。如果我按Ctrl + G,将调用一些命令,因为面板具有命令绑定和焦点(正常的WPF行为)。此外,如果我按Ctrl + H但此时间面板对调用的命令没有命令绑定。在这种情况下,我希望路由引擎切换到文本编辑器并将相同的命令鼓泡到那里。

真实示例

我有一个菜单项,表示粘贴,但焦点在侧面板上。如果我按下菜单命令binded to panel将被执行。假设没有适当的命令绑定到面板。在这种情况下,我想粘贴到文本编辑器中。

代码

此代码或多或少代表此方案。我想按Ctrl + H并执行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 个答案:

答案 0 :(得分:0)

我能够解决这个问题的方法是使用Window.AddHandler方法来捕获所有路由命令事件,然后像textBlock1那样重新引发它们。

textBlock1.RaiseEvent(E);

我还没有这方面的代码,但想法是如果没有处理的路由事件被冒泡到窗口范围,我们捕获所有未处理的事件并从主窗口区域重新提升它们