DelegateCommand and InputBindings

106 views
Skip to first unread message

Corrado Cavalli

unread,
Nov 2, 2008, 4:02:48 AM11/2/08
to wpf-di...@googlegroups.com

After your opinion  I’ve become a DelegateCommand disciple J but I also didn’t like the idea of loosing DisplayText and InputBindings so after some thinking I implemented this…

 

I’ve created a IBindableCommand interface that inherits from ICommand and added the properties I need:

 

interface IBindableCommand:ICommand

  {

    string DisplayText { get; set; }

    InputBindingCollection InputBindings { get; set; }

  }

 

Then created a custom markup extension that does all the funky stuff for me:

 

  [MarkupExtensionReturnType(typeof(IBindableCommand))]

  public class BindCommand : MarkupExtension

  {

    private string commandName;

 

    public BindCommand(string commandName)

    {

      this.commandName = commandName;

    }

 

    public override object ProvideValue(IServiceProvider serviceProvider)

    {

      IProvideValueTarget pvt = serviceProvider.GetService(typeof(IProvideValueTarget)) as IProvideValueTarget;

      if (pvt != null)

      {

        FrameworkElement fe = pvt.TargetObject as FrameworkElement;

        fe.Loaded += new RoutedEventHandler(HandleLoaded);

      }

      return null;

    }

 

    private void HandleLoaded(object sender, RoutedEventArgs e)

    {

      FrameworkElement fe = (sender as FrameworkElement);

      //Use reflection to retrieve provided Command

      PropertyInfo property = fe.DataContext.GetType().GetProperty(this.commandName);

      IBindableCommand command = (IBindableCommand)property.GetValue(fe.DataContext, null);

      ICommandSource source = sender as ICommandSource;

      if (source != null)

      {

        //Button

        Button button = fe as Button;

        if (button != null)

        {

          button.Content = command.DisplayText;

          button.Command = command;

          foreach (InputBinding ib in command.InputBindings)

          {

            button.InputBindings.Add(ib);

          }

        }

        else if (fe as MenuItem != null)

        {

          //MenuItem

          MenuItem menuItem = fe as MenuItem;

          menuItem.Command = command;

          menuItem.Header = command.DisplayText;

          //Handle MenuItem Inputbindings

          if (command.InputBindings != null)

          {

            KeyGesture keyGesture = command.InputBindings[0].Gesture as KeyGesture;

            menuItem.InputGestureText = keyGesture.DisplayString;

            foreach (InputBinding ib in command.InputBindings)

            {

              menuItem.InputBindings.Add(ib);

            }

          }

        }

      }

      //De-register loaded event

      fe.Loaded -= HandleLoaded;

    }

  }

 

It’s basically a mix of a markup extension and attached behavior, but using this I’ve a more friendly approach of applying a Command, like this:

 

<Button

        Command="{local:BindCommand MoveNextCommand}"

        Margin="0,0,10,0"

        HorizontalAlignment="Right" />

 

Where “MoveNextCommand” is the property of my ViewModel that exposes the DelegateCommand implementing IBindableCommand:

 

  public class DelegateCommand: IBindableCommand

  {

  }

 

Of course there is the obvious limitation that it applies only to MenuItems and Buttons, but maybe you have a smart ideas about how can make it more generic.

 

What do you think?

 

Corrado

Josh Smith

unread,
Nov 2, 2008, 9:26:40 AM11/2/08
to wpf-di...@googlegroups.com
You might be able to make this more generic by casting the target element to ICommandSource, which is what all "commanding controls" implement.

Josh

Corrado Cavalli

unread,
Nov 2, 2008, 11:45:26 AM11/2/08
to wpf-di...@googlegroups.com

I did it, but I have no InputBindings and other stuff…

 

Corrado

Marlon Grech

unread,
Nov 2, 2008, 6:08:16 PM11/2/08
to wpf-di...@googlegroups.com
cool stuff dude!!!!
--
Regards
Marlon
WPF Blog - http://marlongrech.wordpress.com/

Reply all
Reply to author
Forward
0 new messages