Frage

Ich bin mit dem RelayCommand in meiner app. Es ist toll, den Code in dem Ansichtsmodell für die Umsetzung, aber wie kann ich binden Tastenanschläge an meinen Befehl?

RoutedUICommand hat seine InputGestures Eigenschaft, die den Befehl macht automatisch aufgerufen werden, wenn ich die Tasten drücken. (Als zusätzlichen Bonus, es macht sogar die Tastenanzeige im MenuItem.) Leider gibt es keine wiederverwendbare Schnittstelle für RoutedUICommand die zusätzlichen Eigenschaften, also kann ich nicht RelayUICommand machen, die die gleiche Magie wird.

Ich habe schon versucht, mit Inputbindings:

<Window.InputBindings>
    <KeyBinding Key="PageUp" Command="{Binding SelectPreviousLayerCommand}"/>
</Window.InputBindings>

Aber das wird mir eine Laufzeitausnahme, weil KeyBinding.Command keine Abhängigkeitseigenschaft ist. (Eigentlich ist es, was beschwert ist darüber KeyBinding ist nicht einmal ein DependencyObject.) Und da mein RelayCommand eine Eigenschaft auf meinem Viewmodel ist (im Gegensatz zu dem statischen Feld entgegengesetzt, der RoutedUICommand konzipiert ist), Datenbindung ist der einzige Weg, ich kenne verweisen sie von XAML.

Wie haben ihr gelöst das? Was ist der beste Weg, um einen Tastendruck auf eine RelayCommand zu binden?

War es hilfreich?

Lösung

Die Command-Eigenschaft der KeyBinding Klasse bietet keine Unterstützung für die Datenbindung. Dieses Problem wird .NET 4.0 gelöst werden, und Sie sollten sie sehen können, in dem kommenden .NET 4.0 Beta 2-Version.

Andere Tipps

Ich glaube nicht, dass Sie dies von XAML tun, für genau die Gründe, die Sie beschreiben.

Ich landete es in dem Code-Behind zu tun. Obwohl es Code ist, ist es nur eine einzige Zeile Code, und noch eher deklarativen, so kann ich damit leben. Allerdings würde Ich hoffe wirklich, dass dies in der nächsten Version von WPF gelöst wird.

Hier ist ein Beispielcodezeile aus einem meiner Projekte:

this.InputBindings.Add(new KeyBinding(
    ((MedicContext)this.DataContext).SynchronizeCommand,
    new KeyGesture(Key.F9)));

SynchronizeCommand in diesem Fall ist eine Instanz RelayCommand, und (natürlich) F9 löst es.

Sie könnten KeyBinding Unterklasse, fügen Sie eine CommandBinding Abhängigkeitseigenschaft, die die Command-Eigenschaft setzt, und fügen Sie es dann wie jede andere Eingabe Bindung an XAML.

public class RelayKeyBinding : KeyBinding
{
    public static readonly DependencyProperty CommandBindingProperty =
        DependencyProperty.Register("CommandBinding", typeof(ICommand), 
        typeof(RelayKeyBinding),
        new FrameworkPropertyMetadata(OnCommandBindingChanged));
    public ICommand CommandBinding
    {
        get { return (ICommand)GetValue(CommandBindingProperty); }
        set { SetValue(CommandBindingProperty, value); }
    }

    private static void OnCommandBindingChanged(
        DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var keyBinding = (RelayKeyBinding)d;
        keyBinding.Command = (ICommand)e.NewValue;
    }
}

XAML:

<Window.InputBindings>
    <RelayKeyBinding 
        Key="PageUp" 
        CommandBinding="{Binding SelectPreviousLayerCommand}" />
</Window.InputBindings>

Sie können die CommandReference Klasse.

Sehr elegant Code und wirkt wie ein Zauber.

Schauen Sie sich auf: Wie verbinde ich einen Tastendruck mit einem DelegateCommand Composite WPF?

Es funktioniert genauso mit RelayCommands, aber es wird nicht Ihren CanExecutes aktualisieren, da der CommandReference nicht Anruf CommandManager.RequerySuggested nicht verwendet Alles, was Sie tun müssen, automatische CanExecute Umwertung zu erreichen, ist in der CommandReference Klasse die folgende Änderung tun

public event EventHandler CanExecuteChanged
{
     add { CommandManager.RequerySuggested += value; }
     remove { CommandManager.RequerySuggested -= value; }
}

Ich schaffe eine Schlüssel Bindung meiner Ansicht nach Modell, das den Befehl und den Schlüssel wie so

Links
        this.KeyBinding = new KeyBinding();
        //set the properties
        this.KeyBinding.Command = this.Command;
        this.KeyBinding.Key = this.Key;
        //modifier keys may or may not be set
        this.KeyBinding.Modifiers = this.ModifierKeys;

dann erstelle ich eine Sammlung von Inputbinding Einzelteilen in meiner Ansicht Modell Wurzel und fügen Sie sie zu den Fenstern Inputbindings in Code meines Fensters hinter

     foreach (var item in applicationViewModel.InputBindingCollection) {
        this.InputBindings.Add(item);
     }

seine schlechte Form Sachen im Code zu tun, hinter, ich weiß, aber ich weiß nicht, wie die Bindung noch zu tun, aber im noch daran zu arbeiten. :) Das einzige, was diese doent mir geben, ist ein Tastenbefehl Modifikator Liste im Menü, aber das ist zu kommen.

Ihre RoutedCommands Unter der Annahme definiert sind statisch:

#region DeleteSelection

    /// <summary>
    /// The DeleteSelection command ....
    /// </summary>
    public static RoutedUICommand DeleteSelection
        = new RoutedUICommand("Delete selection", "DeleteSelection", typeof(ChemCommands));

    #endregion

Bind in XAML so:

<Canvas.InputBindings>
    <KeyBinding Key="Delete" Command="{x:Static Controls:ChemCommands.DeleteSelection}" />
</Canvas.InputBindings>

Grüße,

Tim Haughton

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top