2010-11-15 15 views
9

¿Cómo puedo hacer que Caliburn.Micro asigne un gesto clave a un método de acción en mi ViewModel?¿Cómo puedo enlazar gestos de teclas en Caliburn.Micro?

Por ejemplo, quiero implementar una interfaz con pestañas, y quiero que mi ShellViewModel tenga un método NewTab, que el usuario debería poder invocar presionando Ctrl + T en el teclado.

sé que el marco completo Caliburn tiene soporte para gestos, pero ¿cómo puedo hacer esto usando Caliburn.Micro? ¿Existe alguna forma de enlazar una acción con un RoutedCommand (dado que RoutedCommands ya admite gestos de entrada)? ¿O alguna otra forma de obtener apoyo por gestos?

Respuesta

6

Puede hacerlo mediante la derivación de System.Windows.Interactivity.TriggerBase. Here is an example.

+0

Nunca conseguí que esto funcionara, pero empecé a ver esto de nuevo porque realmente lo necesito ahora. Necesito enfocar el elemento del menú para que se active el gesto. Quiero que se dispare si la ventana está enfocada, ¿cómo puedo arreglar eso? Gracias – Anders

+0

Si coloca la lógica de ejemplo en la ventana principal, ¡congelará toda la vista! – ender

+0

Esta solución no funciona realmente, si lo piensas.Por ejemplo, cuando adjuntas un comando a'MenuItem' y este comando tiene un Gesto (atajo), entonces WPF mostrará la combinación de teclas en el lado derecho (después del texto del menú). – JobaDiniz

6

mecanismo de acciones de Caliburn.Micro se construye en la parte superior de System.Windows.Interactivity. Por lo tanto, puede crear un activador personalizado basado en TriggerBase para hacer lo que desee, incluidos los gestos de teclado globales. ¡Entonces, solo conecta el ActionMessage en tu disparador y viola!

+1

No sé nada sobre TriggerBase o cómo podría vincularse con InputGestures ... ¿dónde podría incluso empezar? –

+1

No es mi voto a favor, por cierto. –

+1

System.Windows.Interactivity es parte de Blend SDK. Si buscas en Blend Behaviors deberías encontrar muchos blogs con muestras. – EisenbergEffect

0

Heredar de ActionMessage de Caliburn (que es un TriggerAction) y conectar el desencadenador derivado al evento KeyDown en XAML y establecer la propiedad ActionMessage.MethodName. Agregue una propiedad al desencadenante derivado de la combinación de teclas que está buscando y anule el método Invoke para filtrar por esa combinación de teclas, llamando a base.Invocar (...) si la clave coincide.

10

he modificado example 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 cada vez Ctr + D se presiona el método será exexuted DoTheMagic. Aquí está el código InputBindingTrigger modificación:

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

// la acción es bloqueada de todos modos por Caliburn en el nivel de invocación Esto no es cierto, todavía se dispara – Anders

+0

sí, se dispara, ¿tiene alguna idea de cómo podría verificarse el método Can si la acción puede disparar? –

+0

No, intenté depurar el código para encontrar una referencia a la propiedad Can, pero no tuve éxito:/ – Anders

0

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 de Caliburn. Puede que no sea tan "ingenioso" como usar Interactivity, pero CanExecute funciona.

<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 su vista de clase, le gire el mando 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 
Cuestiones relacionadas