2010-02-08 5 views
9

Я хочу, чтобы команда на моей модели viewmodel выполнялась на selectionchanged моего ComboBox. Очевидно, Combobox не поддерживает выполнение команд.Поддержка команд WPF в ComboBox

Я создал новый класс, который наследуется от Combox и реализует этот интерфейс.

Когда я пытаюсь просмотреть элемент управления (в дизайнере или в отладке) элемент управления не отображается. У меня нет никаких исключений - мой контроль не пропускает визуальный шаблон или что-то еще?

Спасибо.

public class CommandSourceComboBox : ComboBox, ICommandSource 
{ 
    static CommandSourceComboBox() 
    { 
     DefaultStyleKeyProperty.OverrideMetadata(typeof(CommandSourceComboBox), new FrameworkPropertyMetadata(typeof(CommandSourceComboBox))); 
    } 

    #region ICommandSource Members 

    public ICommand Command 
    { 
     get; 
     set; 
    } 

    public object CommandParameter 
    { 
     get; 
     set; 
    } 

    public IInputElement CommandTarget 
    { 
     get; 
     set; 
    } 

    protected override void OnSelectionChanged(SelectionChangedEventArgs e) 
    { 
     base.OnSelectionChanged(e); 

     if (this.Command != null) 
     { 
      RoutedCommand command = Command as RoutedCommand; 

      if (command != null) 
      { 
       command.Execute(CommandParameter, CommandTarget); 
      } 
      else 
      { 
       ((ICommand)Command).Execute(CommandParameter); 
      } 
     } 
    } 

    #endregion 
} 

ответ

10

Не знаете, почему его изображение не отображается корректно. Может быть, вам нужно выполнить базовый конструктор?

Edit, я тестировал его, и кажется, эта линия:

DefaultStyleKeyProperty.OverrideMetadata(typeof(ComboBoxWithCommand), new FrameworkPropertyMetadata(typeof(ComboBoxWithCommand))); 

ломает это для меня.

Вот моя реализация, и она работает в конструкторе:

public class ComboBoxWithCommand : ComboBox, ICommandSource 
{ 
    private static EventHandler canExecuteChangedHandler; 

    public static readonly DependencyProperty CommandProperty = DependencyProperty.Register("Command", 
                          typeof(ICommand), 
                          typeof(ComboBoxWithCommand), 
                          new PropertyMetadata((ICommand)null, 
                          new PropertyChangedCallback(CommandChanged))); 

    public ICommand Command 
    { 
     get 
     { 
      return (ICommand)GetValue(CommandProperty); 
     } 
     set 
     { 
      SetValue(CommandProperty, value); 
     } 

    } 

    public static readonly DependencyProperty CommandTargetProperty = DependencyProperty.Register("CommandTarget", 
                            typeof(IInputElement), 
                            typeof(ComboBoxWithCommand), 
                            new PropertyMetadata((IInputElement)null)); 

    public IInputElement CommandTarget 
    { 
     get 
     { 
      return (IInputElement)GetValue(CommandTargetProperty); 
     } 
     set 
     { 
      SetValue(CommandTargetProperty, value); 
     } 
    } 

    public static readonly DependencyProperty CommandParameterProperty = DependencyProperty.Register("CommandParameter", 
                            typeof(object), 
                            typeof(ComboBoxWithCommand), 
                            new PropertyMetadata((object)null)); 

    public object CommandParameter 
    { 
     get 
     { 
      return (object)GetValue(CommandParameterProperty); 
     } 
     set 
     { 
      SetValue(CommandParameterProperty, value); 
     } 
    } 

    public ComboBoxWithCommand() : base() { } 


    private static void CommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
    { 
     ComboBoxWithCommand cb = (ComboBoxWithCommand)d; 
     cb.HookUpCommand((ICommand)e.OldValue, (ICommand)e.NewValue); 
    } 

    private void HookUpCommand(ICommand oldCommand, ICommand newCommand) 
    { 
     if (oldCommand != null) 
     { 
      RemoveCommand(oldCommand, newCommand); 
     } 
     AddCommand(oldCommand, newCommand); 
    } 

    private void RemoveCommand(ICommand oldCommand, ICommand newCommand) 
    { 
     EventHandler handler = CanExecuteChanged; 
     oldCommand.CanExecuteChanged -= handler; 
    } 

    private void AddCommand(ICommand oldCommand, ICommand newCommand) 
    { 
     EventHandler handler = new EventHandler(CanExecuteChanged); 
     canExecuteChangedHandler = handler; 
     if (newCommand != null) 
     { 
      newCommand.CanExecuteChanged += canExecuteChangedHandler; 
     } 
    } 
    private void CanExecuteChanged(object sender, EventArgs e) 
    { 

     if (this.Command != null) 
     { 
      RoutedCommand command = this.Command as RoutedCommand; 

      // If a RoutedCommand. 
      if (command != null) 
      { 
       if (command.CanExecute(this.CommandParameter, this.CommandTarget)) 
       { 
        this.IsEnabled = true; 
       } 
       else 
       { 
        this.IsEnabled = false; 
       } 
      } 
      // If a not RoutedCommand. 
      else 
      { 
       if (Command.CanExecute(CommandParameter)) 
       { 
        this.IsEnabled = true; 
       } 
       else 
       { 
        this.IsEnabled = false; 
       } 
      } 
     } 
    } 

    protected override void OnSelectionChanged(SelectionChangedEventArgs e) 
    { 
     base.OnSelectionChanged(e); 

     if (this.Command != null) 
     { 
      RoutedCommand command = this.Command as RoutedCommand; 

      if (command != null) 
      { 
       command.Execute(this.CommandParameter, this.CommandTarget); 
      } 
      else 
      { 
       ((ICommand)Command).Execute(CommandParameter); 
      } 
     } 
    } 
} 
+0

Это здорово! Я точно хочу. К сожалению, теперь все стили, примененные к ComboBox, не относятся к объектам ComboBoxWithCommand. Знаете ли вы, как легко стираются стили? Или мне нужно дублировать стиль и настраивать тип ComboBoxWithCommand? – KrisTrip

+1

Ничего, я понял. Я добавил следующее к моему шаблону стиля: