If you try to define CommandBindings
or InputBindings
as resources in your App.xaml
, you will find that you cannot use them, because XAML doesn't allow you to use either:
<Window ... CommandBindings="{StaticResource commandBindings}">
or to set command bindings with a style setter:
<Setter Property="CommandBindings" Value="{StaticResource commandBindings}">
because neither of these properties have a "set" accessor. Using the idea in this post, I came up with a clean way of using resources from App.xaml
or any other resource dictionary.
First you define your command bindings and input bindings indirectly, like you would any other resource:
<InputBindingCollection x:Key="inputBindings">
<KeyBinding Command="Help" Key="H" Modifiers="Ctrl"/>
</InputBindingCollection>
<CommandBindingCollection x:Key="commandBindings">
<CommandBinding Command="Help" Executed="CommandBinding_Executed"/>
</CommandBindingCollection>
and then you refer to them from the XAML of another class:
<Window ...>
<i:Interaction.Behaviors>
<local:CollectionSetterBehavior Property="InputBindings" Value="{StaticResource inputBindings}"/>
<local:CollectionSetterBehavior Property="CommandBindings" Value="{StaticResource commandBindings}"/>
</i:Interaction.Behaviors>
...
</Window>
The CollectionSetterBehavior
is a reusable behavior that doesn't "set" the property to it's value, but instead clears the collection, and re-populates it. So the collection doesn't change, only it's contents.
Here's the source for the behavior:
public class CollectionSetterBehavior : Behavior<FrameworkElement>
{
public string Property
{
get { return (string)GetValue(PropertyProperty); }
set { SetValue(PropertyProperty, value); }
}
public static readonly DependencyProperty PropertyProperty =
DependencyProperty.Register("Property", typeof(string), typeof(CollectionSetterBehavior), new UIPropertyMetadata(null));
public IList Value
{
get { return (IList)GetValue(ValueProperty); }
set { SetValue(ValueProperty, value); }
}
public static readonly DependencyProperty ValueProperty =
DependencyProperty.Register("Value", typeof(IList), typeof(CollectionSetterBehavior), new UIPropertyMetadata(null));
protected override void OnAttached()
{
var propertyInfo = AssociatedObject.GetType().GetProperty(Property);
var property = propertyInfo.GetGetMethod().Invoke(AssociatedObject, null) as IList;
property.Clear();
foreach (var item in Value) property.Add(item);
}
}
If you are not familiar with behaviors, first add this namespace:
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
and add the corresponding reference to your project.
ApplicationCommands.MyCommand
? If not this doesn't answer my question. – Machos