Как прикрепить команды к проверке и снятию флажка?

В моей ViewModel у меня есть две команды:

ICommand ExecuteMeOnCheck { get; }
ICommand ExecuteMeOnUncheck { get; }

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


person GraemeF    schedule 06.06.2009    source источник
comment
Что плохого в том, чтобы загромождать код программной части этим? Это самое простое решение для понимания, и оно по-прежнему сохраняет разделение View-ViewModel.   -  person Cameron MacFarland    schedule 07.06.2009


Ответы (5)


Самый простой способ, который я нашел для этого, — это заимствование кода. Я также думаю, что вы не хотите выставлять два события для изменения состояния. Сделайте свою команду CheckedChangedCommand вместо Checked и Unchecked. Привяжите свойство зависимостей CheckBox.IsChecked к свойству в вашем ViewModelClass. Таким образом, когда ваша команда выполняется, вы просто проверяете это значение в своей ViewModel.

Сначала начните использовать DelegateCommand из набора инструментов WPF ViewModel. . Из твоего поста не понятно ты или нет.

Затем загрузите архив .zip с вкладки "Загрузки" по этой ссылке.

В архиве есть класс EventBehaviourFactory, упрощающий настройку DependencyProperty. Вернувшись на вкладку «Главная» по приведенной выше ссылке, Сэмюэл расскажет вам, как связать команду в вашем XAML с ViewModel. Вот:

<TextBox ff:TextBoxBehaviour.TextChangedCommand="{Binding TextChanged}"/>

Я использовал три класса (DelegateCommand, EventBehaviourFactory и TextBoxBehaviour) строка за строкой, и событие TextChanged сработало в моем проекте примерно через пять минут.

Шаблон для расширения его на другие элементы управления, как вам нужно, тоже прост. Мне удалось подключить ListBox.SelectionChanged таким же образом. Создайте новый класс ControlBehaviour и замените «Control» на «TextBox» во всех экземплярах и присоедините DependencyProperty к новому событию.

Это прекрасно, когда ваш код пуст!

person Eddie Butt    schedule 06.06.2009
comment
Большое спасибо за эту подсказку. Я столкнулся с описанной выше проблемой около 3 часов назад и, наконец, нашел это, и это именно то, что мне было нужно. Я уже боялся, что придется расстаться с прекрасной чистотой вложения всей логики в модель. Единственным решением, которое я мог придумать, было направить события в модель из представления, но это было бы и вполовину не так приятно, как сделать это таким образом. - person Thorsten Lorenz; 26.07.2009

Я сделал это с помощью триггера «IsChecked», который устанавливает команду.

e.g.

<Style x:Key="checkBoxStyle" TargetType="{x:Type CheckBox}">
      <Style.Triggers>
        <Trigger Property="IsChecked" Value="True">
          <Setter Property="Command"
                  Value="{Binding AddThingCommand}" />
        </Trigger>
        <Trigger Property="IsChecked" Value="False">
          <Setter Property="Command"
                  Value="{Binding RemoveThingCommand}" />
        </Trigger>
      </Style.Triggers>
    </Style>
person Timje    schedule 23.04.2010


Это относится к ответу Эдди.

Я немного поиграл с ним, и это здорово, я также создал небольшой шаблон для создания новых команд. Я использую его с Sharpdevelop в качестве фрагмента кода. Просто вставьте следующее в свой код (например, через фрагмент):

#region $nameCommand

    public static readonly DependencyProperty $nameCommand =
        EventBehaviourFactory.CreateCommandExecutionEventBehaviour(
            Control.$nameEvent, "$nameCommand", typeof (ControlBehavior));

    public static void Set$nameCommand(DependencyObject o, ICommand value)
    {
        o.SetValue($nameCommand, value);
    }

    public static ICommand Get$nameCommand(DependencyObject o)
    {
        return o.GetValue($nameCommand) as ICommand;
    }

    #endregion 

Затем выполните поиск, замените «$ name» именем события/команды, например. МышьEnter

Обратите внимание, важно убедиться, что вы выбрали правильное имя класса для владельца (в моем случае ControlBehavior.

Я прикрепляю класс, который я создал для общих команд мыши, в надежде, что другие люди тоже им поделятся, и мы не просто реализуем одно и то же снова и снова, где мы могли бы сэкономить много времени, поделившись. Вот мой полный класс ControlBehavior (до сих пор я реализовал только те события, которые мне были нужны):

public static class ControlBehavior
    {
        #region MouseEnterCommand

        public static readonly DependencyProperty MouseEnterCommand =
            EventBehaviourFactory.CreateCommandExecutionEventBehaviour(
                Control.MouseEnterEvent, "MouseEnterCommand", typeof (ControlBehavior));

        public static void SetMouseEnterCommand(DependencyObject o, ICommand value)
        {
            o.SetValue(MouseEnterCommand, value);
        }

        public static ICommand GetMouseEnterCommand(DependencyObject o)
        {
            return o.GetValue(MouseEnterCommand) as ICommand;
        }

        #endregion

        #region MouseLeaveCommand

        public static readonly DependencyProperty MouseLeaveCommand =
            EventBehaviourFactory.CreateCommandExecutionEventBehaviour(
                Control.MouseLeaveEvent, "MouseLeaveCommand", typeof (ControlBehavior));

        public static void SetMouseLeaveCommand(DependencyObject o, ICommand value)
        {
            o.SetValue(MouseLeaveCommand, value);
        }

        public static ICommand GetMouseLeaveCommand(DependencyObject o)
        {
            return o.GetValue(MouseLeaveCommand) as ICommand;
        }

        #endregion


        #region MouseDoubleClickCommand

        public static readonly DependencyProperty MouseDoubleClickCommand = 
            EventBehaviourFactory.CreateCommandExecutionEventBehaviour(
            Control.MouseDoubleClickEvent, "MouseDoubleClickCommand", typeof (ControlBehavior));

        public static void SetMouseDoubleClickCommand(Control o, ICommand command)
        {
            o.SetValue(MouseDoubleClickCommand, command);
        }

        public static void GetMouseDoubleClickCommand(Control o)
        {
            o.GetValue(MouseDoubleClickCommand);
        }

        #endregion

        #region MouseLeftButtonDownCommand

        public static readonly DependencyProperty MouseLeftButtonDownCommand =
            EventBehaviourFactory.CreateCommandExecutionEventBehaviour(
                Control.MouseLeftButtonDownEvent, "MouseLeftButtonDownCommand", typeof (ControlBehavior));

        public static void SetMouseLeftButtonDownCommand(DependencyObject o, ICommand value)
        {
            o.SetValue(MouseLeftButtonDownCommand, value);
        }

        public static ICommand GetMouseLeftButtonDownCommand(DependencyObject o)
        {
            return o.GetValue(MouseLeftButtonDownCommand) as ICommand;
        }

        #endregion

    }

Используя приведенный выше шаблон, мне потребовалось всего несколько секунд для каждой команды.

person Thorsten Lorenz    schedule 26.07.2009

хорошо, вы можете наследовать от элемента управления checkBox, добавить две команды в качестве свойств (Свойства зависимости), а затем переопределить методы OnChecked и OnUnchecked и запустить каждую команду в соответствующем месте.

person abdelkarim    schedule 06.06.2009