Как я могу связать ключевые жесты в Caliburn.Micro? - PullRequest
10 голосов
/ 15 ноября 2010

Как я могу заставить Caliburn.Micro сопоставить жест ключа с методом действия в моей ViewModel?

Например, я хочу реализовать интерфейс с вкладками и хочу, чтобы в моей ShellViewModel был метод NewTab, который пользователь должен иметь возможность вызывать, нажимая Ctrl + T на клавиатуре.

Я знаю, что полная платформа Caliburn поддерживает жесты, но как я могу сделать это с помощью Caliburn.Micro? Возможно, есть какой-нибудь способ привязать действие к RoutedCommand (поскольку RoutedCommands уже поддерживают жесты ввода)? Или другой способ получить поддержку жестов?

Ответы [ 5 ]

12 голосов
/ 23 ноября 2011

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

<i:Interaction.Triggers>
        <common:InputBindingTrigger>
            <common:InputBindingTrigger.InputBinding>
                <KeyBinding Modifiers="Control" Key="D"/>
            </common:InputBindingTrigger.InputBinding>
            <cl:ActionMessage MethodName="DoTheMagic"/>
        </common:InputBindingTrigger>
    </i:Interaction.Triggers>

И всякий раз, когда нажимается Ctr + D, метод DoTheMagic будет отменен. Вот модифицированный код InputBindingTrigger:

public class InputBindingTrigger : TriggerBase<FrameworkElement>, ICommand
  {
    public static readonly DependencyProperty InputBindingProperty =
      DependencyProperty.Register("InputBinding", typeof (InputBinding)
        , typeof (InputBindingTrigger)
        , new UIPropertyMetadata(null));

    public InputBinding InputBinding
    {
      get { return (InputBinding) GetValue(InputBindingProperty); }
      set { SetValue(InputBindingProperty, value); }
    }

    public event EventHandler CanExecuteChanged = delegate { };

    public bool CanExecute(object parameter)
    {
      // action is anyway blocked by Caliburn at the invoke level
      return true;
    }

    public void Execute(object parameter)
    {
      InvokeActions(parameter);
    }

    protected override void OnAttached()
    {
      if (InputBinding != null)
      {
        InputBinding.Command = this;        
        AssociatedObject.Loaded += delegate {
          var window = GetWindow(AssociatedObject);
          window.InputBindings.Add(InputBinding);
        };
      }
      base.OnAttached();
    }

    private Window GetWindow(FrameworkElement frameworkElement)
    {
      if (frameworkElement is Window)
        return frameworkElement as Window;

      var parent = frameworkElement.Parent as FrameworkElement;      
      Debug.Assert(parent != null);

      return GetWindow(parent);
    }
  }
6 голосов
/ 02 мая 2011

Вы можете сделать это, наследуя от System.Windows.Interactivity.TriggerBase Вот пример .

6 голосов
/ 15 ноября 2010

Механизм действий Caliburn.Micro построен поверх System.Windows.Interactivity.Таким образом, вы можете создать собственный триггер на основе TriggerBase, чтобы делать все что угодно, в том числе глобальные жесты клавиатуры.Затем просто подключите ActionMessage к вашему триггеру и альту!

0 голосов
/ 21 апреля 2016

Если вы направили команду через View to View Model, вы можете управлять CanExecute из View View. Я использовал этот метод в нескольких проектах Caliburn. Может быть не так "гладко", как при использовании интерактивности, но CanExecute работает.

<UserControl x:Class="MyView"
      ...
      Name="View"
>

  <UserControl.InputBindings>
    <KeyBinding Key="F5" 
                Command="{Binding RefreshCommand, ElementName=View, Mode=OneWay}" />
  </UserControl.InputBindings>

  <Button Command="{Binding Path=RefreshCommand, ElementName=View, Mode=OneWay}"/>

В вашем классе View вы связываете команду с моделью представления, на которую ссылается свойство MyView.DataContext.

Class MyView

    Public Property RefreshCommand As _
    New RelayCommand(AddressOf Refresh,
                     Function()
                         If ViewModel Is Nothing Then
                             Return False
                         Else
                             Return ViewModel.CanRefresh
                         End If
                     End Function)

    Private Sub Refresh()
        ViewModel.Refresh()
    End Sub

    Private ReadOnly Property ViewModel As MyViewModel
        Get
            Return DirectCast(DataContext, MyViewModel)
        End Get
    End Property

End Class
0 голосов
/ 08 июля 2011

Наследуйте от ActionMessage Caliburn (который является TriggerAction) и присоедините производный триггер к событию KeyDown в XAML и установите свойство ActionMessage.MethodName.Добавьте свойство к производному триггеру того, какую комбинацию клавиш вы ищете, и переопределите метод Invoke для фильтрации по этой комбинации клавиш, вызывая base.Invoke (...), если ключ совпадает.

...