开发者

TreeViewItems and Keybinding

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.Regi开发者_如何学编程sterAttached("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();
        }

    }


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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜