Привязать к UserControl RoutedCommand из родительского окна

Я пытаюсь создать UserControl, который отображает многостраничное изображение и позволяет пользователю масштабировать, поворачивать и просматривать изображение. Одна часть, с которой у меня возникла проблема, - это правильная настройка сочетаний клавиш. Я понял, что мне нужно настроить InputBindings для класса Window, в котором размещен UserControl. Я понял, как создать InputBinding в коде позади, но я ожидаю много сочетаний клавиш, и я думаю, что их в XAML будет проще. Вот пример проекта, в котором я это тестирую:

MainWindow.xaml

<Window x:Class="CommandTest.Window1"  
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"  
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"  
xmlns:local="clr-namespace:CommandTest"  
Title="Window1" Height="300" Width="344">
<Window.InputBindings>
    <KeyBinding
        Key="N"
        CommandTarget="x:UCon"
        />
</Window.InputBindings>

<StackPanel>
    <local:NestedControl x:Name="UCon">
    </local:NestedControl>
</StackPanel>
</Window>  

MainWindow.Xaml.cs

using System.Windows;
using System.Windows.Input;

namespace CommandTest
{
    public partial class Window1 : Window
    {
         public Window1()
         {
             InitializeComponent();
             KeyGesture keyg = new KeyGesture(Key.OemPlus, ModifierKeys.Control);

             KeyBinding kb = new KeyBinding((ICommand)UCon.Resources["Commands.ZoomOut"], keyg);

             kb.CommandTarget = UCon;

             this.InputBindings.Add(kb);   
         }

     }
}

UserControl1.xaml

<UserControl x:Class="CommandTest.NestedControl"  
   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"  
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

    <UserControl.Resources>
        <!-- UI commands. -->        
        <RoutedCommand x:Key="Commands.ZoomOut" />        
    </UserControl.Resources>

    <UserControl.CommandBindings>
        <CommandBinding x:Name="ZoomCommand" Command="{StaticResource Commands.ZoomOut}" CanExecute="ZoomCommand_CanExecute" Executed="ZoomCommand_Executed"/>        
    </UserControl.CommandBindings>
    <Button Command="{StaticResource Commands.ZoomOut}">Zoom</Button>
</UserControl>  

UserControl1.xaml.cs

using System.Windows.Controls;
using System.Windows.Input;

namespace CommandTest
{
    public partial class NestedControl : UserControl
    {
        public NestedControl()
        {
            InitializeComponent();
        }

        private void ZoomCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = true;
        }

        private void ZoomCommand_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            System.Windows.MessageBox.Show("Zoom", "Zoom");
        }        
    }
}

person Gariig    schedule 11.11.2010    source источник


Ответы (1)


Вместо того, чтобы привязывать ключ к окну, привяжите его к самой команде (вы можете сделать это в конструкторе для ZoomCommand, если это пользовательская команда):

ZoomCommand.InputGestures.Add(new KeyGesture(Key.N));

Затем в конструкторе для UserControl:

Window.GetWindow(this).CommandBindings.Add(new CommandBinding(new ZoomCommand(), ZommCommand_handler));
person Greg Sansom    schedule 11.11.2010
comment
Является ли создание команды в коде лучшим способом, чем создание команды в XAML? Также означает ли это, что вы не можете добавить InputBinding к хосту UserControl в XAML? Кроме того, это решение не работает. UserControl1 не имеет KeyboardFocus, поэтому InputBinding никогда не срабатывает. Если вы нажмете кнопку, а затем используете KeyGesture, MessageBox покажет - person Gariig; 12.11.2010
comment
Используете ли вы код или XAML для создания команд, действительно зависит от вас — ни то, ни другое не лучше. Я выбрал код здесь, потому что он требует меньше строк и может быть немного проще для понимания. Я отредактировал свой ответ, чтобы вместо этого привязать команду к окну. - person Greg Sansom; 15.11.2010