Могу ли я иметь несколько командных привязок для одной команды на одном элементе управления? - PullRequest
9 голосов
/ 18 февраля 2010

У меня есть UserControl, который добавляет CommandBinding в свою коллекцию CommandBindings для обработки конкретной команды. Позже я использую этот элемент управления в окне и хочу добавить еще одну привязку к тому же элементу управления, чтобы добавить дополнительное поведение. Проблема, однако, в том, что когда я делаю это, кажется, что когда я добавляю другую CommandBinding в коллекцию CommandBindings элемента управления, он заменяет любую привязку, которая уже была создана для той же команды. Так что похоже, что элемент управления может иметь только одну привязку CommandBinding для каждого элемента управления, это правильно?

См. Пример кода ниже, в котором делается попытка установить две привязки команд для одной и той же команды сохранения.

<Window x:Class="MultipleCommandBindings.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300">
<Window.CommandBindings>
    <CommandBinding Command="Save"
                    Executed="CommandBinding_Executed" />
    <CommandBinding Command="Save"
                    Executed="CommandBinding_Executed" />
</Window.CommandBindings>
<Grid>
    <Button Height="23"
            HorizontalAlignment="Right"
            Margin="0,0,25,88"
            Name="button1"
            VerticalAlignment="Bottom"
            Width="75"
            Command="Save">Button</Button>
</Grid>

Первоначально я ожидал исключения во время компиляции или во время выполнения, когда писал этот код, но был удивлен, что он не жаловался. Затем я был разочарован, поскольку мой обработчик CommandBinding_Executed вызывается только один раз, а не дважды, как я надеялся.

Обновление: После небольшого тестирования кажется, что мой второй CommandBinding не перезаписывает мой первый, но вместо этого кажется, что, хотя я не устанавливаю Handled в true в моем обработчике событий, первая привязка команды поглощает Команду. На данный момент я почти уверен, что решение моей проблемы состоит в том, чтобы понять, почему перенаправленная команда не распространяется за пределы первого обработчика, даже если для параметра Handled не задано значение true.

Обновление: Я нашел этот большой маленький кусочек информации, которая только подтверждает некоторые странные особенности маршрутизации команд в WPF.

Обновление: Одна мысль о том, как обойти тот факт, что кажется, что для каждой команды может быть только одна эффективная команда CommandBinding, заключается в том, что класс CommandBinding по умолчанию представляет Executed и CanExecute как события, которые, как и все события, могут иметь несколько обработчиков. Идея состоит в том, чтобы иметь какой-то другой способ, кроме стандартного метода CommandBindings.Add, для добавления дополнительных обработчиков в команду. Возможно, это можно сделать с помощью метода расширения класса Control и в сочетании с пользовательским классом CompositeCommandBinding, который позволяет объединять несколько привязок в одну основную привязку.

Ответы [ 2 ]

3 голосов
/ 19 февраля 2010

До сих пор мне удалось найти обходной путь для этой проблемы, который заключается в обработке команды на двух разных уровнях в логическом дереве. В приведенном ниже примере я обрабатываю команду «Сохранить» в своей сетке, а затем снова в элементе «Окно».

<Window x:Class="MultipleCommandBindings.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300">
<Window.CommandBindings>
    <CommandBinding Command="Save"
                    Executed="CommandBinding_Executed2"/>
</Window.CommandBindings>
<Grid>
    <Grid.CommandBindings>
        <CommandBinding Command="Save"
                        Executed="CommandBinding_Executed1" />
    </Grid.CommandBindings>

    <Button Height="23"
            HorizontalAlignment="Right"
            Margin="0,0,25,88"
            Name="button1"
            VerticalAlignment="Bottom"
            Width="75"
            Command="Save">Button</Button>
</Grid>

Чтобы заставить это работать, мой код должен также вручную распространять выполнение Команды на следующий уровень.

    private void CommandBinding_Executed1(object sender, ExecutedRoutedEventArgs e)
    {
        System.Diagnostics.Debug.WriteLine("Executed 1!");
        var command = e.Command as RoutedUICommand;
        command.Execute(e.Parameter, this);
    }

    private void CommandBinding_Executed2(object sender, ExecutedRoutedEventArgs e)
    {
        System.Diagnostics.Debug.WriteLine("Executed 2!");
    }

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

1 голос
/ 18 февраля 2010

Я не знаю ответа на ваш вопрос, но использование Reflector звучит для меня разумно.

Мне интересно, зачем ты это делаешь? Может быть, имеет смысл использовать шаблон Composite для агрегирования поведения, а не пытаться объединять привязки команд?

...