views:

480

answers:

1

I want to have a command on my viewmodel execute on the selectionchanged of my ComboBox. Obviously Combobox does not support executing commands.

I have created a new class that inherits from Combox and implements this interface.

When I try to view the control (in the designer or in debug) the control doesn't show. I don't get any exceptions - is my control missing a visual template or something?

Thanks.

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
}
+1  A: 

Not sure why its not displayed correctly. Maybe you need to execute the base constructor?

Edit, I actually tested it and it seems this line:

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

breaks it for me.

Here is my implementation and it works in the designer:

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);
            }
        }
    }
}
Michael