denver
denver

Reputation: 3135

Binding to KeyBinding Gesture

I am trying to set up an input gesture as follows:

<Window.InputBindings>
    <KeyBinding Command="{Binding MyCommand}" Gesture="{x:Static local:Resources.MyCommandGesture}" />
</Window.InputBindings>

Here Resources is a resource .resx file and MyCommandGesture is a string defined in it. This produces the following exception:

Unable to cast object of type System.String to type System.Windows.Input.InputGesture.

There is no problem if I just replace the binding with the string from the resource file (such as Gesture="F2"). Any suggestions?

Edit: We can achieve the desired result in code behind by doing something like the following:

KeyGestureConverter kgc = new KeyGestureConverter();
KeyGesture keyGestureForMyCommand = (KeyGesture)kgc.ConvertFromString(Resources.MyCommandGesture);
this.InputBindings.Add(new KeyBinding(VM.MyCommand, keyGestureForMyCommand));

I was hoping to find a XAML solution.

Upvotes: 1

Views: 2532

Answers (1)

James Harcourt
James Harcourt

Reputation: 6379

This doesn't work because you're expected to place a valid value from the System.Windows.Input.Key enumeration into the Gesture property of your KeyBinding.

If you do this:

Gesture="F2"

... even though it feels like you're putting in a string, you're actually putting in a valid named constant from the enumeration, hence it works.

However, if you use this:

Gesture="{x:Static local:Resources.MyCommandGesture}"

It bypasses the enum mapping because you're using the x:Static markup extension and ultimately are saying "this is a string". Even if the value is equal to a valid constant name from the "Key" enum, it won't work.

If you really can't live with putting the key name in XAML, I personally wouldn't use the resources file. Rather, I'd have a class which defines them as the correct type i.e. KeyGestures:

public class KeyGestures
{
    public static KeyGesture KeyCommandAction1 { get { return new KeyGesture(Key.F1); } }
    public static KeyGesture KeyCommandAction2 { get { return new KeyGesture(Key.F2); } }
}

And use in XAML accordingly:

<KeyBinding Command="{Binding MyCommand1}" Gesture="{x:Static local:KeyGestures.KeyCommandAction1}" />
<KeyBinding Command="{Binding MyCommand2}" Gesture="{x:Static local:KeyGestures.KeyCommandAction2}" />

Upvotes: 1

Related Questions