События RoutedCommands Executed и PreviewExecuted - PullRequest
6 голосов
/ 12 января 2011

Моя проблема в том, что я хотел бы обрабатывать команды в нескольких местах. Например, у меня есть свой пользовательский элемент управления UserControl, в котором кнопка привязана к какой-либо команде. У меня есть привязка команды в этом элементе управления, но у меня также есть привязка команды в окне, которое использует этот элемент управления.

Моя цель - выполнить некоторые действия внутри элемента управления, не прерывая обработку команды в окне.

Я попытался поэкспериментировать с событиями Executed и PreviewExecuted, но безуспешно. Затем я смоделировал проблему в одном окне (код приведен ниже).

<Window x:Class="CommandingEvents.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:CommandingEvents="clr-namespace:CommandingEvents" 
    Title="Window1" Height="300" Width="300">
<Window.CommandBindings>
    <CommandBinding 
        Command="{x:Static CommandingEvents:Window1.Connect}"
        Executed="CommandBindingWindow_Executed"
        PreviewExecuted="CommandBindingWindow_PreviewExecuted"/>
</Window.CommandBindings>
<Grid>
    <Grid.CommandBindings>
        <CommandBinding 
        Command="{x:Static CommandingEvents:Window1.Connect}"
        Executed="CommandBindingGrid_Executed"
        PreviewExecuted="CommandBindingGrid_PreviewExecuted" />
    </Grid.CommandBindings>
    <Button Command="{x:Static CommandingEvents:Window1.Connect}" 
            CommandTarget="{Binding RelativeSource={RelativeSource Self}}"
            Content="Test" HorizontalAlignment="Center" VerticalAlignment="Center" />
</Grid>

namespace CommandingEvents
{
    public partial class Window1
    {
        public static readonly RoutedUICommand Connect = new
            RoutedUICommand("Connect", "Connect", typeof(Window1));

        public Window1()
        {
            InitializeComponent();
        }

        private void CommandBindingWindow_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            Console.WriteLine("CommandBindingWindow_Executed");
            e.Handled = false;
        }

        private void CommandBindingGrid_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            Console.WriteLine("CommandBindingGrid_Executed");
            e.Handled = false;
        }

        private void CommandBindingWindow_PreviewExecuted(object sender, ExecutedRoutedEventArgs e)
        {
            Console.WriteLine("CommandBindingWindow_PreviewExecuted");
            e.Handled = false;
        }

        private void CommandBindingGrid_PreviewExecuted(object sender, ExecutedRoutedEventArgs e)
        {
            Console.WriteLine("CommandBindingGrid_PreviewExecuted");
            e.Handled = false;
        }
    }
}

Когда я нажимаю кнопку, выводится только «CommandBindingWindow_PreviewExecuted». Это почему? Я пытался установить e.Handled на false, но это не имеет значения. Кто-нибудь может объяснить это поведение?

1 Ответ

9 голосов
/ 02 февраля 2011

Я понятия не имею, почему это происходит (и как это не ошибка), но вот что было написано в WPF wiki :

Есть особенностьо CommandBinding, который чрезвычайно интересен и важен для понимания.

CommandManager использует перенаправленные события для уведомления различных объектов CommandBinding о том, что было выполнено выполнение команды (посредством жестов по умолчанию, привязок ввода, явным образом и т.*

До сих пор это довольно просто.Однако, что более важно, это то, что CommandBinding пометит перенаправленное событие из CommandManager как обработанное, как только обработчик будет выполнен (PreviewExecuted или Executed).

Наконец, даже если ваш обработчик имеет прототип, который соответствуетделегат с именем ExecutedRoutedEventHandler, событие Executed из CommandBinding является не RoutedEvent, а обычным событием CLR.Установка или оставление флага e.Handled на false ничего не изменит.

Поэтому, как только вызывается обработчик Executed или PreviewExecuted, RoutedCommand остановит свою маршрутизацию.

...