1
votes

I'm trying to set keybinding on my TreeView items using technique described here(the first answer). So I have a TreeView in XAML, an ICommand property defined in TreeView item's ViewModel, and a helper class registering attached property to support keybinding in TreeViewItem's style. But every time the command is only invoked on the first item of my TreeView no matter which item was actually selected. Why is that and how can I fix it? Or may be there is some better way to set keybinding on TreeViewItems without breaking MVVM pattern?

XAML

<TreeView x:Name="tr" ItemsSource="{Binding Root}">
        <TreeView.ItemContainerStyle>
            <Style TargetType="{x:Type TreeViewItem}">
                <Setter Property="local:AttachedTVIBinding.InputBindings">
                    <Setter.Value>
                        <InputBindingCollection>
                            <KeyBinding Key="A" Command="{Binding SomeCommand}"/>
                            <MouseBinding Gesture="LeftDoubleClick" Command="{Binding SomeCommand}"/>
                        </InputBindingCollection>
                    </Setter.Value>
                </Setter>
            </Style>
        </TreeView.ItemContainerStyle>
</TreeView>

TreeViewItem's ViewModel

public class ConfigurationNodeViewModel : INotifyPropertyChanged
{
        private DelegateCommand _someCommand;

        public DelegateCommand SomeCommand
        {
            get { return _editDesignCommand; }
        }
}

Helper class (exactly like in the link provided)

public class AttachedTVIBinding : Freezable
    {
        public static readonly DependencyProperty InputBindingsProperty =
            DependencyProperty.RegisterAttached("InputBindings", typeof(InputBindingCollection), typeof(AttachedTVIBinding),
            new FrameworkPropertyMetadata(new InputBindingCollection(),
            (sender, e) =>
            {
                var element = sender as UIElement;
                if (element == null) return;
                element.InputBindings.Clear();
                element.InputBindings.AddRange((InputBindingCollection)e.NewValue);
            }));

        public static InputBindingCollection GetInputBindings(UIElement element)
        {
            return (InputBindingCollection)element.GetValue(InputBindingsProperty);
        }

        public static void SetInputBindings(UIElement element, InputBindingCollection inputBindings)
        {
            element.SetValue(InputBindingsProperty, inputBindings);
        }

        protected override Freezable CreateInstanceCore()
        {

            return new AttachedTVIBinding();
        }

    }
1
Can you provide us more insight or your code on this? What is your keyBinding actually trying to do? How does it cater for the selected treeview item? Where are you doing the attached property binding?WPF-it
I've include some code in the initial post. What I want to accomplish is the command being executed within the ViewModel of the currently selected TreeViewItem every time user presses some key. But maybe I complicate my task and there is a simpler way for thisNatalia
Hi, I have the same problem, did you manage to find a solution?dzavala

1 Answers

2
votes

Here is a 3 years late answer but might be useful for someone.

The solution is to use a style which applies a non-shared resource containing your KeyBinding and MouseBinding elements by setting x:Shared="False". This allows to create more than 1 instance of InputBindingCollection as WPF by default creates only a single instance of a style.

<InputBindingCollection x:Key="myBindings" x:Shared="False">
    <KeyBinding Key="A" Command="{Binding SomeCommand}"/>
    <MouseBinding Gesture="LeftDoubleClick" Command="{Binding SomeCommand}"/>
</InputBindingCollection>

<Style TargetType="{x:Type TreeViewItem}">
    <Setter Property="local:AttachedTVIBinding.InputBindings" Value="{DynamicResource myBindings}"/>
</Style>

Please note that x:Shared can only be used within a compiled ResourceDictionary. You can also use the same ResourceDictionary in which you have defined a style for TreeViewItem but InputBindingCollection needs to be placed above this style.