2010-10-15 27 views
9

me han declarado <InputBindings>C#/WPF: no KeyBinding activación de comandos

<UserControl.InputBindings> 
    <KeyBinding Key="C" Modifiers="Ctrl" Command="{Binding CopyImageCommand}" /> 
    <KeyBinding Key="V" Modifiers="Ctrl" Command="{Binding PasteImageCommand}" /> 
</UserControl.InputBindings> 

Para propósitos de prueba, he añadido botones unidos a esos comandos también

<Button Command="{Binding CopyImageCommand}" Content="Copy" /> 
<Button Command="{Binding PasteImageCommand}" Content="Paste" /> 

he notado que cuando el botón de pasta es habilitado, cuando presiono Ctrl-V no sucede nada. Ctrl-C parece funcionar. Para eso, se selecciona un elemento del cuadro de lista, no estoy seguro si hace alguna diferencia. ¿Alguien sabe por qué mi PasteImageCommand no se activa?

estoy usando .NET 4 por cierto

ACTUALIZACIÓN

Un código más completo snipplet

<UserControl x:Class="QuickImageUpload.Views.ShellView" 
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
      xmlns:vm="clr-namespace:QuickImageUpload.ViewModels" 
      mc:Ignorable="d" 
      d:DesignHeight="300" d:DesignWidth="300"> 
    <UserControl.InputBindings> 
     <KeyBinding Key="C" Modifiers="Ctrl" Command="{Binding CopyImageCommand}" /> 
     <KeyBinding Key="V" Modifiers="Ctrl" Command="{Binding PasteImageCommand}" /> 
    </UserControl.InputBindings> 
    <UserControl.DataContext> 
     <vm:ShellViewModel /> 
    </UserControl.DataContext> 
    <Grid> 
     <Grid.RowDefinitions> 
      <RowDefinition Height="50" /> 
      <RowDefinition Height="*" /> 

ACTUALIZACIÓN

descubrí que necesito para poner el KeyBindings en MainWindow, pero los comandos están en el ViewModel, ¿cómo puedo establecer enlaces de teclas en el ShellView que luego se une a los comandos en el ShellViewModel?

+0

¿Puede usted por favor post donde se InputBinding especificados? Es posible que lo pongas en el lugar equivocado. – Euphoric

+0

@Euphoric, he puesto mis InputBindings en UserControl ShellView. Descubrí que funciona cuando los coloco en MainWindow, pero necesito establecer el modelo de vista en ShellViewModel, no es realmente correcto, creo, ¿cómo puedo manejar esto? –

+1

@JiewMeng: Hola jiew! tengo casi el mismo problema ¿Has encontrado alguna solución? – Jalal

Respuesta

0

¿Está usando 3.5 o 4?

En 3.5 su "característica". UserControl.InputBindings no es parte del árbol de dataContext por lo que no se puede unir a elementos de clase, que está obligado a parent. p.ej. DataBinding no funciona y debe establecer DataBinding o KeyBinding completo en código a mano.

Su fijados en 4.

+0

Estoy usando .NET 4 –

+0

Actualicé mi publicación con un snipplet de código más completo que muestra dónde están los enlaces de entrada declaró –

3

Asegúrese de que usted no está teniendo errores de enlace. Establece el DataContext del control de usuario, pero asegúrese de que los comandos se puedan vincular a él. A veces, WPF solo usa el orden de aparición, y el DataContext se configura más tarde que los comandos.

Probablemente, la ventana de salida de VS ya muestra errores de enlace para los comandos. Trata de poner la definición de DataContext en la parte superior (y enséñate a hacer esto para todas las vistas).

0

Tuve una situación similar en la que los eventos relacionados con Key se escuchaban solo en la Vista de Shell y no cambiaban a la vista real donde se presionó la tecla. Para solucionar este problema, escribí un pequeño comportamiento adjunto para establecer el foco en el control del usuario o el elemento de marco para recibir el enfoque en la carga inicial y de esa manera los golpes de tecla son escuchados por el elemento UI que quiero escuchar.

public class FocusBehavior 
{ 
    public static readonly DependencyProperty IsFocusedProperty = 
     DependencyProperty.RegisterAttached("IsFocused", typeof(bool?),typeof(FocusBehavior), 
     new UIPropertyMetadata(false, new PropertyChangedCallback(OnFocusChanged))); 
    public static bool? GetIsFocused(DependencyObject obj) 
    { 
     return (bool?)obj.GetValue(IsFocusedProperty); 
    } 
    public static void SetIsFocused(DependencyObject obj, bool? value) 
    { 
     obj.SetValue(IsFocusedProperty, value); 
    } 
    private static void OnFocusChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args) 
    { 
     var frameworkElement = sender as FrameworkElement; 
     if (frameworkElement == null) return; 
     if (args.OldValue == null) return; 
     if (args.NewValue == null) return; 
     if ((bool)args.NewValue) 
     { 
      frameworkElement.Loaded += OnFrameworkElementLoaded; 
     } 
    } 

    private static void OnFrameworkElementLoaded(object sender, RoutedEventArgs args) 
    { 
     var frameworkElement = sender as FrameworkElement; 
     frameworkElement.Focus(); 
     frameworkElement.Loaded -= OnFrameworkElementLoaded; 
     var textControl = frameworkElement as JHATextEditor; 
     if (textControl == null) return; 
     textControl.SelectAll(); 
    } 
} 

y lo utilizó como este en uno de mis puntos de vista de lista de la siguiente manera -

<GridViewColumn Width="Auto" Header="Value"> 
        <GridViewColumn.CellTemplate> 
         <DataTemplate> 
          <Grid HorizontalAlignment="Stretch" MinWidth="100"> 
           <TextBlock Text="{Binding FieldValue}" /> 
          </Grid> 
          <DataTemplate.Triggers> 
           <DataTrigger Binding="{Binding IsSelected}" Value="True"> 
            <Setter Property="local:FocusBehavior.IsFocused" TargetName="FieldValueEditor" Value="True" /> 
           </DataTrigger> 
          </DataTemplate.Triggers> 
         </DataTemplate> 
        </GridViewColumn.CellTemplate> 
       </GridViewColumn> 

Espero que esto ayude.

-vj

0

En este caso se puede proporcionar combinaciones de teclas en su declaración RoutedCommand:

public static RoutedCommand PasteImageCommand = new RoutedCommand("PasteImageCommand", typeof(YourType), new InputGestureCollection { new KeyGesture(Key.V, ModifierKeys.Control)}); 

esto debería funcionar.

4

Para evitar KeyBindings codificados, he obtenido Josh Smith RelayCommand-Class y ha añadido cosas relacionadas con el acceso directo:

class UIRelayCommand : RelayCommand, INotifyPropertyChanged 
{ 
    private static Dictionary<ModifierKeys, string> modifierText = new Dictionary<ModifierKeys, string>() 
    { 
     {ModifierKeys.None,""}, 
     {ModifierKeys.Control,"Ctrl+"}, 
     {ModifierKeys.Control|ModifierKeys.Shift,"Ctrl+Shift+"}, 
     {ModifierKeys.Control|ModifierKeys.Alt,"Ctrl+Alt+"}, 
     {ModifierKeys.Control|ModifierKeys.Shift|ModifierKeys.Alt,"Ctrl+Shift+Alt+"}, 
     {ModifierKeys.Windows,"Win+"} 
    }; 

    private Key _key; 
    public Key Key 
    { 
     get { return _key; } 
     set { _key = value; RaisePropertyChanged("Key"); RaisePropertyChanged("GestureText"); } 
    } 

    private ModifierKeys _modifiers; 
    public ModifierKeys Modifiers 
    { 
     get { return _modifiers; } 
     set { _modifiers = value; RaisePropertyChanged("Modifiers"); RaisePropertyChanged("GestureText");} 
    } 

    public string GestureText 
    { 
     get { return modifierText[_modifiers] + _key.ToString(); } 
    } 

    public UIRelayCommand(Action<object> execute, Predicate<object> canExecute, Key key, ModifierKeys modifiers) 
     : base(execute, canExecute) 
    { 
     _key = key; 
     _modifiers = modifiers; 
    } 


    public event PropertyChangedEventHandler PropertyChanged; 

    public void RaisePropertyChanged(string name) 
    { 
     if (PropertyChanged != null) 
      PropertyChanged(this, new PropertyChangedEventArgs(name)); 
    } 
} 

continuación, crear el comando en el modelo de vista:

private ICommand _newFileCommand; 
public ICommand NewFileCommand 
{ 
    get 
    { 
     if (_newFileCommand == null) 
      _newFileCommand = new UIRelayCommand(p => OnNewFile(p), p => CanNewFile(p), Key.N, ModifierKeys.Control); 
     return _newFileCommand; 
    } 
} 
protected void OnNewFile(object p) 
{ 
    //open file... 
} 
protected bool CanNewFile(object p) 
{ 
    return true; 
} 

y enlazarlo en la vista :

<Window.InputBindings> 
    <KeyBinding Command="{Binding NewFileCommand}" Key="{Binding NewFileCommand.Key}" Modifiers="{Binding NewFileCommand.Modifiers}" /> 
</Window.InputBindings> 
... 
<MenuItem Header="New File" Command="{Binding NewFileCommand}" InputGestureText="{Binding NewFileCommand.GestureText}" /> 

Con este enfoque puedo permitir que el usuario se ajuste los accesos directos en tiempo de ejecución (en la configuración de mi ventana)

+1

+1 ... Excelente solución! Un pequeño error tipográfico en el último fragmento de código: Modifiers = "{Binding NewFileCommand.Modifier}" debería ser Modifiers = "{Binding NewFileCommand.Modifiers}". –

0

Prueba esto:

<UserControl.InputBindings> 
     <KeyBinding Key="C" Modifiers="Control" Command="{Binding CopyImageCommand}" /> 
     <KeyBinding Key="V" Modifiers="Control" Command="{Binding PasteImageCommand}" /> 
    </UserControl.InputBindings> 
Cuestiones relacionadas