Olav Haugen
Olav Haugen

Reputation: 1351

Dynamic Menu With Key Gestures

I have an .NET 4.0 application using Caliburn.Micro. I want to create a dynamic menu such that I don't need to write XAML code for each menu item. Additionally, I want to associate each command with a key gesture.

I have an interface IAction:

public interface IAction
{
    string Name { get; }
    InputGesture Gesture { get; }
    ICommand Command { get; }      
}

In my ViewModel I expose a list of IActions:

private List<IAction> _actions;
public List<IAction> Actions
{
    get { return _actions; }
    set
    {
        _actions = value;
        NotifyOfPropertyChange(()=> Actions);
    }
}

I bind my Toolbar to the actions as follows:

<ToolBar>
    <Menu ItemsSource="{Binding Actions}">
        <Menu.ItemContainerStyle>
            <Style TargetType="MenuItem">
                <Setter Property="Header" Value="{Binding Name}" />
                <Setter Property="Command" Value="{Binding Command}" />
            </Style>
        </Menu.ItemContainerStyle>
    </Menu>
</ToolBar>

All of the above works.

What I'm missing is the databinding of the Key Gesture.

Everywhere I read, I only find examples with static definitions of Window.InputBindings such as:

<Window.InputBindings>
  <KeyBinding Key="B" Modifiers="Control" Command="ApplicationCommands.Open" />
</Window.InputBindings>

It would be great if I simply could encapsulate the Window.InputBindings in an ItemsControl, but that doesn't work.

Any of you know how to dynamically bind Window.InputBindings?

Thanks!

Upvotes: 1

Views: 1024

Answers (1)

Matěj Z&#225;bsk&#253;
Matěj Z&#225;bsk&#253;

Reputation: 17272

Key gestures have to be created for the window object (if they are to have window-wide effect).

I guess you could create a custom derived window object which would have a dependency property named for example BindableInputBindings. This property in its OnChanged callback would add/remove the key bindings every time the source collection changed.

EDIT: There may be some errors.

public class WindowWithBindableKeys: Window {

    protected static readonly DependencyProperty BindableKeyBindingsProperty = DependencyProperty.Register(
        "BindableKeyBindings", typeof(CollectionOfYourKeyDefinitions), typeof(WindowWithBindableKeys), new FrameworkPropertyMetadata("", new PropertyChangedCallback(OnBindableKeyBindingsChanged))
    );

    public CollectionOfYourKeyDefinitions BindableKeyBindings
    {
        get
        {
            return (string)GetValue(BindableKeyBindingsProperty);
        }
        set
        {
            SetValue(BindableKeyBindingsProperty, value);
        }
    }

    private static void OnBindableKeyBindingsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        (d as WindowWithBindableKeys).InputBindings.Clear();

        // add the input bidnings according to the BindableKeyBindings
    }

}

Then in XAML

<mynamespace:WindowWithBindableKeys BindableKeyBindings={Binding YourSourceOfKeyBindings} ... > ...

Upvotes: 2

Related Questions