2010-10-15 8 views
9

I <InputBindings>C#/WPF: KeyBinding Auslösung nicht Befehl

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

Für Testzwecke erklärt habe, habe ich Tasten auf diese Befehle zu gebunden hinzugefügt

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

Ich bemerkte, dass, wenn die Paste-Taste ist aktiviert, wenn ich Strg-V drücke passiert nichts. Strg-C scheint zu funktionieren. Dazu ist ein Listenfeld ausgewählt, ich bin mir nicht sicher, ob es einen Unterschied macht. Jeder weiß, warum ist meine PasteImageCommand nicht auslösend?

Ich bin mit .NET 4 btw

UPDATE

Ein Code voller

<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

snipplet

Ich fand heraus, ich brauche das setzen KeyBindings im MainWindow, aber die Befehle sind in der ViewModel, wie kann ich Tastenbelegungen in der ShellView setzen, die dann an Befehle in der ShellViewModel bindet?

+0

Können Sie bitte posten, wo angegeben sind Inputbinding? Es ist möglich, dass Sie es falsch platzieren. – Euphoric

+0

@Euphoric, Ich habe meine InputBindings in der UserControl ShellView gesetzt. Ich habe herausgefunden, dass es funktioniert, wenn ich sie in das MainWindow setze, aber ich muss das View-Modell auf ShellViewModel einstellen, nicht wirklich korrekt. Ich denke, wie kann ich damit umgehen? –

+1

@JiewMeng: Hi jiew! Ich habe fast das gleiche Problem. Hast du irgendeine Lösung gefunden? – Jalal

Antwort

0

Verwenden Sie 3,5 oder 4?

In 3.5 seine "Funktion". UserControl.InputBindings ist nicht Teil der DataContext-Struktur, sodass Sie nicht an Elemente der Klasse binden können, die an Parent gebunden sind. z.B. DataBinding wird nicht funktionieren und Sie müssen DataBinding oder die gesamte KeyBinding in Code von Hand festlegen.

Die in 4 fixiert

+0

Ich benutze .NET 4 –

+0

Ich habe meinen Beitrag mit einem volleren Code-Snipplet aktualisiert, der zeigt, wo die Eingabe-Bindungen sind –

3

Vergewissern Sie sich, dass Sie nicht verbindlich Fehler haben. Sie legen den DataContext des Benutzersteuerelements fest, aber stellen Sie sicher, dass die Befehle an es binden können. Manchmal verwendet WPF nur die Reihenfolge der Darstellung und der DataContext wird später als die Befehle festgelegt.

Wahrscheinlich zeigt das Ausgabefenster von VS bereits Bindungsfehler für die Befehle. Versuchen Sie, die DataContext-Definition oben zu platzieren (und lernen Sie, dies für alle Ansichten zu tun).

0

Ich hatte eine ähnliche Situation, wo in den Key related events wurden nur in der Shell-Ansicht zu hören und war nicht auf die tatsächliche Ansicht tune, wo die Taste gedrückt wurde. Um dieses Problem zu beheben, schrieb ich ein kleines angehängtes Verhalten, um den Fokus auf das Benutzersteuerelement oder das Framework-Element zu setzen, um den Fokus auf das anfängliche Laden zu erhalten. Auf diese Weise werden die Schlüsselstriche von dem Benutzeroberflächenelement gehört, das ich hören möchte.

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

und benutzte es, wie dies in einem meiner Liste Ansichten wie unten -

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

Hoffnung, das hilft.

-vj

0

In diesem Fall Sie keybindings in Ihrer RoutedCommand Erklärung liefern:

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

Diese funktionieren sollte.

4

hartkodierte KeyBindings zu vermeiden, habe ich Josh Smiths abgeleitet RelayCommand-Class und hinzugefügt Shortcut-related stuff:

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

und es in der Ansicht binden:

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

dann den Befehl im Ansichtsmodell erstellen :

<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}" /> 

Mit diesem Ansatz kann ich dem Benutzer erlauben, anzupassen die Verknüpfungen zur Laufzeit (in meiner Konfiguration-Fenster)

+1

+1 ... Ausgezeichnete Lösung! Ein kleiner Tippfehler im letzten Code-Snippet: Modifiers = "{Binding NewFileCommand.Modifier}" sollte Modifiers = "{Binding NewFileCommand.Modifiers}" sein. –

0

Try this:

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