Pregunta

¿Cómo puedo obtener Caliburn.Micro para asignar un gesto clave para un método de acción en mi modelo de vista?

Por ejemplo, quiero implementar una interfaz con pestañas, y yo quiero que mi ShellViewModel tener un método newtab que el usuario debe ser capaz de invocar pulsando Ctrl + T en el teclado.

Yo sé que el marco completo Caliburn tiene soporte para gestos, pero ¿cómo puedo hacer esto usando Caliburn.Micro? ¿Hay quizá una cierta manera de enlazar una acción a un RoutedCommand (ya RoutedCommands ya soportan gestos de entrada)? O alguna otra forma de obtener soporte de gestos?

¿Fue útil?

Solución

Puede hacerlo mediante la derivación de System.Windows.Interactivity.TriggerBase. Aquí está un ejemplo .

Otros consejos

para habilitar el soporte para atajos de teclado globales. Sólo tiene que añadir el código folowing a la vista:

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

Y siempre Ctr + D se presiona el método será exexuted DoTheMagic. Aquí está el código InputBindingTrigger modificado:

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);
    }
  }

mecanismo de acciones de Caliburn.Micro se construye en la parte superior de System.Windows.Interactivity. Por lo tanto, puede crear un disparador personalizado basado en TriggerBase a hacer lo que quiera, incluyendo los gestos de teclado globales. A continuación, sólo tiene que enchufar el ActionMessage en su gatillo y la viola!

Heredar del ActionMessage de Caliburn (que es un TriggerAction) y adjuntar el gatillo derivado al evento KeyDown en XAML y establecer la propiedad ActionMessage.MethodName. Añadir un alojamiento a la activación obtenido de la combinación de teclas lo que busca y reemplazar el método Invoke para filtrar por esa combinación de teclas, llamando base.Invoke (...) si los partidos clave.

Si Marshal un comando a través de la vista a la vista del modelo se puede controlar el CanExecute del Modelo Vista. He estado usando este método en múltiples proyectos Caliburn. Puede que no sea como "mancha" como el uso de la interactividad, pero funciona 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}"/>

En la clase de vista, se cablea el comando a la vista del modelo que se hace referencia en la propiedad 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
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top