TreeViewItems и связывание клавиш - PullRequest
1 голос
/ 19 сентября 2011

Я пытаюсь установить привязку клавиш для своих элементов TreeView, используя методику, описанную здесь (первый ответ).Итак, у меня есть TreeView в XAML, свойство ICommand, определенное в ViewModel элемента TreeView, и вспомогательный класс, регистрирующий присоединенное свойство для поддержки связывания клавиш в стиле TreeViewItem.Но каждый раз команда вызывается только для первого элемента моего TreeView, независимо от того, какой элемент был фактически выбран.Почему это и как я могу это исправить?Или, может быть, есть какой-то лучший способ установить привязку клавиш к TreeViewItems, не нарушая шаблон MVVM?

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>

ViewViewModel TreeViewItem

public class ConfigurationNodeViewModel : INotifyPropertyChanged
{
        private DelegateCommand _someCommand;

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

вспомогательный класс (точно так же, какв приведенной ссылке)

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 Ответ

1 голос
/ 23 октября 2014

Это ответ с опозданием на 3 года, но он может быть полезен для кого-то.

Решение состоит в том, чтобы использовать стиль, который применяет ресурс без общего доступа, содержащий ваши элементы KeyBinding и MouseBinding, путем установки x: Shared = "False". Это позволяет создать более 1 экземпляра InputBindingCollection, поскольку WPF по умолчанию создает только один экземпляр стиля.

<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>

Обратите внимание, что x: Shared может использоваться только внутри скомпилированного ResourceDictionary. Вы также можете использовать тот же ResourceDictionary, в котором вы определили стиль для TreeViewItem, но InputBindingCollection необходимо поместить выше этого стиля.

...