2010-10-15 1 views
9

ho dichiarato <InputBindings>C#/WPF: non KeyBinding innescando Comando

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

A scopo di verifica, ho aggiunto i pulsanti legati a quei comandi troppo

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

Ho notato che quando il pulsante di pasta è abilitato, quando premo Ctrl-V non succede nulla. Ctrl-C sembra funzionare. Per questo, un elemento della casella di riepilogo è selezionato, non sono sicuro che faccia alcuna differenza. Qualcuno sa perché il mio PasteImageCommand non si attiva?

Sto usando .NET 4 btw

UPDATE

Un codice più piena 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="*" /> 

UPDATE

ho scoperto che ho bisogno di mettere il KeyBindings in MainWindow, ma i comandi si trovano nello ViewModel, come posso impostare i binding dei tasti nel ShellView che quindi si collega ai comandi nello ShellViewModel?

+0

Potete per favore post in cui sono specificati InputBinding? È possibile che tu l'abbia messo nel posto sbagliato. – Euphoric

+0

@Euphoric, ho messo il mio InputBindings in UserControl ShellView. Ho scoperto che funziona quando li metto in MainWindow, ma ho bisogno di impostare il modello di visualizzazione su ShellViewModel, non proprio corretto, penso, come posso gestirlo? –

+1

@JiewMeng: Ciao! ho quasi lo stesso problema hai trovato qualche soluzione? – Jalal

risposta

0

Si sta utilizzando 3.5 o 4?

Nella 3.5 la "caratteristica". UserControl.InputBindings non fa parte della struttura dataContext, quindi non è possibile associarsi a elementi di classe, che sono associati al padre. per esempio. DataBinding non funziona e devi impostare DataBinding o tutta KeyBinding nel codice a mano.

sua fissati 4.

+0

Sto usando .NET 4 –

+0

Ho aggiornato il mio post con uno snipplet di codice più completo che mostra dove sono i collegamenti di input dichiarato –

3

Assicurarsi che non si hanno errori di associazione. Si imposta DataContext del controllo utente, ma assicurarsi che i comandi possano associarsi ad esso. A volte, WPF utilizza solo l'ordine di apparizione e DataContext viene impostato successivamente ai comandi.

Probabilmente, la finestra di output di VS mostra già errori di associazione per i comandi. Prova a mettere la definizione DataContext in cima (e insegnati a farlo per tutte le visualizzazioni).

0

Ho avuto una situazione simile in cui gli eventi relativi alla chiave venivano ascoltati solo in Shell View e non erano in sintonia con la vista effettiva in cui era stato premuto il tasto. Per risolvere questo problema, ho scritto un piccolo comportamento collegato per impostare lo stato attivo sul controllo utente o l'elemento framework per ricevere lo stato attivo sul caricamento iniziale e in questo modo i tratti chiave sono ascoltati dall'elemento dell'interfaccia utente che voglio ascoltare.

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

e lo ha utilizzato come questo in uno dei miei punti di vista della lista, come di seguito -

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

Spero che questo aiuti.

-vj

0

In questo caso è possibile fornire combinazioni di tasti nella dichiarazione RoutedCommand:

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

questo dovrebbe funzionare.

4

Per evitare KeyBindings hardcoded, ho derivato Josh Smiths RelayCommand-Class e ha aggiunto roba di scelta rapida relativi:

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

quindi creare il comando nella ViewModel:

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

e associarlo nella 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 questo approccio posso consentire all'utente di regolare i tasti di scelta rapida in fase di esecuzione (nella mia configurazione-window)

+1

+1 ... Ottima soluzione! Un errore di battitura nell'ultimo frammento di codice: Modificatori = "{Binding NewFileCommand.Modifier}" dovrebbe essere Modificatori = "{Binding NewFileCommand.Modifiers}". –

0

provare questo:

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