У меня может быть несколько CommandBindings для той же Команды на том же управлении?

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

См. пример кода, ниже которого попытки установить два CommandBindings для того же Сохраняют Команду.



    
    


    

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

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

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

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

9
задан jpierson 4 March 2010 в 07:36
поделиться

2 ответа

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

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

1
ответ дан 3 November 2019 в 07:47
поделиться

Этот тип вещей - хлеб и масло F #. Ты можешь попробовать. Для синтаксического анализа используйте рекурсивный спуск, затем можно запустить дерево, которое приводит к результатам. Если вы управляете языком ввода, вы можете получить доступ с помощью операции цитаты.

-121--3357706-

Подход правильный. Я делал это точно несколько раз.

Можно сделать его явным в коде, в котором защищен конструктор по умолчанию BaseMessage.

Также необходимо объявить значение дискриминатора в базовом классе.

Я предпочитаю строковые значения для дискриминаторов, так как это более ясно при выполнении SQL запросов или отчетов. Кроме того, поскольку экземпляры BaseMessage shoudl не существуют, для значения дискриминатора в будет использоваться значение null.

<class name="BaseMessage" table="Messages" discriminator-value="null">
    <id />
    <discriminator column="SourceID" />
    <subclass name="NMessage" discriminator-value="NMessage">
    </subclass>
    <subclass name="BMessage" discriminator-value="BMessage">
    </subclass>
    <subclass name="CMessage" discriminator-value="CMessage">
    </subclass>
</class>

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

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

class BaseMessage
{
    public virtual string MessageType { return null; }
}

class NMessage : BaseMessage
{
    public override string MessageType { return "NMessage"; }
}

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

  • access = "property" - это тип по умолчанию
  • type = "String" - все используемые типы можно вывести из класса .NET
  • column = "COL" - значение по умолчанию совпадает с именем
  • аналогично для элемента столбца id

Все подклассы сообщений имеют свойство Body, поэтому переместите Если это поле может быть длиннее, чем varchar базы данных, оно должно быть текстовым столбцом и иметь тип = "StringCLob", который сопоставляется строкам в .NET

<class name="BaseMessage" table="Messages" discriminator-value="null">
    <id name="MessageID">
        <generator class="native" />
    </id>
    <discriminator column="SourceID"/>
    <property name="DateCreated" />
    <property name="DatePublished" />
    <many-to-one name="User" column="UserID" cascade="none" lazy="false" fetch="join" outer-join="true" />
    <property name="Body" type="StringCLob" />
    <subclass name="NMessage" discriminator-value="NMessage">
    </subclass>
    <subclass name="BMessage" discriminator-value="BMessage">
        <property name="Title" />
    </subclass>
    <subclass name="CMessage" discriminator-value="CMessage">
        <property name="Url" />
    </subclass>
</class>
-121--4320875-

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

<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!");
    }

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

3
ответ дан 3 November 2019 в 07:47
поделиться
Другие вопросы по тегам:

Похожие вопросы: