views:

538

answers:

1

Hi,

I would like to use the same custom RoutedCommand for 2 buttons, which are in separate windows.

In order to not repeat the code, i want to define the command somewhere in the app and bind it to both buttons.

I thought of using Style to achieve that. Below, I reproduce my issue in a simple sample.

I declare the Style in App.Xaml :

<Application.Resources>
    <Style TargetType="{x:Type Window}">
        <Setter Property="CommandBindings">
        <Setter.Value>
    <!--<Window.CommandBindings>--> <!--I tried with or without this. Doesn't change-->
                <CommandBinding Command="{x:Static local:App.testBindingCommand}"
                    Executed="OnExecuted" CanExecute="OnCanExecute" />
      <!--</Window.CommandBindings>-->
        </Setter.Value>
        </Setter>
    </Style>
 </Application.Resources>

And the custom command in App.Xaml.cs :

public static RoutedCommand testBindingCommand = new RoutedCommand();

    private void OnExecuted(object sender, ExecutedRoutedEventArgs e)
    {
        System.Windows.MessageBox.Show("OnExecuted");
    }

    private void OnCanExecute(object sender, CanExecuteRoutedEventArgs e)
    {
        System.Windows.MessageBox.Show("OnCanExecute");

        e.CanExecute = true;
    }

The compiler does not like the code and give an error :

error MC3080: The Property Setter 'CommandBindings' cannot be set because it does not have an accessible set accessor.

AFAIK, the Window class has a CommandBindings property.

1) Is the use of Style to declare global CommandBindings correct ? If not, how can i do ?

2) Why the property CommandBindings can't be set by the style ?

Thanks!

+1  A: 

You are getting that error message because you are setting the value of the CommandBindings property (which is of type CommandBindingsCollection) to an instance of CommandBinding. Even if the property has a setter (which it doesn't), you can't set a CommandBinding to a CommandBindingsCollection.

Consider the case of binding a command normally:

<Window>
    <Window.CommandBindings>
        <CommandBinding Command="{x:Static local:App.testBindingCommand}"
            Executed="OnExecuted" CanExecute="OnCanExecute" />
    </Window.CommandBindings>
</Window>

This isn't setting the CommandBinding to the CommandBindings property, but rather adding it to the CommandBindings collection of the Window.

Do you have to use a RoutedCommand? Maybe it would be better to use a different implementation of ICommand - maybe one that calls a delegate when the command is executed. Kent Boogaart has an implementation of DelegateCommand that could work (there are many other similar implementations floating around, too - or you could write your own).

Andy
Indeed you are right for the binding between CommandBindingsCollection and CommandBinding. That's why i tried <Window.CommandBindings> at first (see the comments in app.xaml)I will take a lokk at DelegateCommand
rockeye
You were right. Using RelayCommand (or DelegateCommand) is much more easier and avoid using CommandBinding. Thanks
rockeye