Sie können sich einen reinen XAML-Ansatz machen, indem Sie ein angehängtes Verhalten erstellen .
Etwas wie das:
public static class InputBindingsManager
{
public static readonly DependencyProperty UpdatePropertySourceWhenEnterPressedProperty = DependencyProperty.RegisterAttached(
"UpdatePropertySourceWhenEnterPressed", typeof(DependencyProperty), typeof(InputBindingsManager), new PropertyMetadata(null, OnUpdatePropertySourceWhenEnterPressedPropertyChanged));
static InputBindingsManager()
{
}
public static void SetUpdatePropertySourceWhenEnterPressed(DependencyObject dp, DependencyProperty value)
{
dp.SetValue(UpdatePropertySourceWhenEnterPressedProperty, value);
}
public static DependencyProperty GetUpdatePropertySourceWhenEnterPressed(DependencyObject dp)
{
return (DependencyProperty)dp.GetValue(UpdatePropertySourceWhenEnterPressedProperty);
}
private static void OnUpdatePropertySourceWhenEnterPressedPropertyChanged(DependencyObject dp, DependencyPropertyChangedEventArgs e)
{
UIElement element = dp as UIElement;
if (element == null)
{
return;
}
if (e.OldValue != null)
{
element.PreviewKeyDown -= HandlePreviewKeyDown;
}
if (e.NewValue != null)
{
element.PreviewKeyDown += new KeyEventHandler(HandlePreviewKeyDown);
}
}
static void HandlePreviewKeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.Enter)
{
DoUpdateSource(e.Source);
}
}
static void DoUpdateSource(object source)
{
DependencyProperty property =
GetUpdatePropertySourceWhenEnterPressed(source as DependencyObject);
if (property == null)
{
return;
}
UIElement elt = source as UIElement;
if (elt == null)
{
return;
}
BindingExpression binding = BindingOperations.GetBindingExpression(elt, property);
if (binding != null)
{
binding.UpdateSource();
}
}
}
Dann setzen Sie in Ihrer XAML die InputBindingsManager.UpdatePropertySourceWhenEnterPressedProperty
Eigenschaft auf diejenige, die Sie aktualisieren möchten, wenn Sie die EnterTaste drücken. So was
<TextBox Name="itemNameTextBox"
Text="{Binding Path=ItemName, UpdateSourceTrigger=PropertyChanged}"
b:InputBindingsManager.UpdatePropertySourceWhenEnterPressed="TextBox.Text"/>
(Sie müssen nur sicherstellen, dass das Stammelement Ihrer XAML-Datei eine xmlns-CLR-Namespace-Referenz für "b" enthält, die auf den Namespace verweist, in den Sie den InputBindingsManager eingefügt haben.)
UpdatePropertySourceWhenEnterPressed
Wechsel von einem gültigen Wert zu einem anderen gültigen Wert erfolgt, können Sie dasPreviewKeyDown
Ereignis unnötig abbestellen und erneut abonnieren . Stattdessen müssen Sie nur prüfen, ob dase.NewValue
istnull
oder nicht. Wenn nichtnull
, abonnieren Sie; Andernfalls, wennnull
, dann abbestellen.So habe ich dieses Problem gelöst. Ich habe einen speziellen Event-Handler erstellt, der in den Code dahinter eingeht:
Dann habe ich dies als KeyUp-Ereignishandler in der XAML hinzugefügt:
Der Ereignishandler verwendet seine
sender
Referenz, um zu veranlassen, dass seine eigene Bindung aktualisiert wird. Da der Ereignishandler in sich geschlossen ist, sollte er in einer komplexen DataTemplate funktionieren. Dieser eine Ereignishandler kann jetzt allen Textfeldern hinzugefügt werden, die diese Funktion benötigen.quelle
KeyBinding
diese Methode in der XAML verwendet, um sie auszulösen, da meine Benutzeroberfläche über ein "Standard" -Steuerelement verfügt, das die Eingabetaste abfängt. Sie müssen es in dieser TextBox abfangen, um zu verhindern, dass es den UI-Baum an das Steuerelement "Standard" weiterleitet.Ich glaube nicht, dass es eine "reine XAML" -Methode gibt, um das zu tun, was Sie beschreiben. Sie können eine Bindung so einrichten, dass sie aktualisiert wird, wenn sich der Text in einer TextBox ändert (und nicht, wenn die TextBox den Fokus verliert), indem Sie die UpdateSourceTrigger- Eigenschaft wie folgt festlegen :
Wenn Sie UpdateSourceTrigger auf "Explicit" setzen und dann das PreviewKeyDown-Ereignis der TextBox behandeln (nach der Eingabetaste suchen), können Sie das erreichen, was Sie möchten, aber es würde Code-Behind erfordern. Vielleicht würde eine Art angehängte Eigenschaft (ähnlich meiner EnterKeyTraversal- Eigenschaft) für Sie funktionieren.
quelle
Sie können ganz einfach ein eigenes Steuerelement erstellen, das von TextBox erbt, und es im gesamten Projekt wiederverwenden.
Ähnliches sollte funktionieren:
Es kann eine Möglichkeit geben, diesen Schritt zu umgehen, aber ansonsten sollten Sie wie folgt binden (mit Explicit):
quelle
Wenn Sie die Lösungen von Ben und ausadmin kombinieren, erhalten Sie eine sehr MVVM-freundliche Lösung:
... was bedeutet, dass Sie das
TextBox
selbst als Parameter an das übergebenCommand
.Dies führt dazu, dass Sie so
Command
aussehen (wenn Sie eineDelegateCommand
Implementierung im Stil Ihrer VM verwenden):Diese
Command
Implementierung kann für jedenTextBox
und am besten keinen Code im CodeBehind verwendet werden, obwohl Sie dies möglicherweise in eine eigene Klasse einfügen möchten, damitSystem.Windows.Controls
in Ihrer VM keine Abhängigkeiten bestehen . Dies hängt davon ab, wie streng Ihre Code-Richtlinien sind.quelle
Hier ist ein Ansatz, der mir recht einfach und einfacher erscheint als das Hinzufügen eines AttachedBehaviour (was auch eine gültige Lösung ist). Wir verwenden den Standard-UpdateSourceTrigger (LostFocus für TextBox) und fügen dann der Eingabetaste eine Eingabebindung hinzu, die an einen Befehl gebunden ist.
Das xaml ist wie folgt
Dann sind die Befehlsmethoden
Und die TextBox ist an die Eigenschaft gebunden
Bisher scheint dies gut zu funktionieren und fängt das Enter Key-Ereignis in der TextBox ab.
quelle
Dies ist keine Antwort auf die ursprüngliche Frage, sondern eine Erweiterung der akzeptierten Antwort von @Samuel Jack. Ich habe in meiner eigenen Bewerbung Folgendes getan und war beeindruckt von der Eleganz von Samuels Lösung. Es ist sehr sauber und sehr wiederverwendbar, da es auf jeder Steuerung verwendet werden kann, nicht nur auf der
TextBox
. Ich dachte, das sollte mit der Community geteilt werden.Wenn Sie ein Fenster mit tausend Fenstern haben
TextBoxes
, die alle zum Aktualisieren der Bindungsquelle bei der Eingabe erforderlich sind, können Sie dieses Verhalten an alle anhängen, indem Sie die unten stehende XAML in IhreWindow
Resources
einfügen, anstatt sie an jede Textbox anzuhängen. Zuerst müssen Sie natürlich das angehängte Verhalten gemäß Samuels Beitrag implementieren .Sie können den Bereich bei Bedarf jederzeit einschränken, indem Sie den Stil in die Ressourcen eines der
Grid
untergeordneten Elemente des Fensters (dh a ) einfügen, das die Zieltextfelder enthält.quelle
Wenn Sie MultiBinding mit Ihrer TextBox verwenden, müssen Sie
BindingOperations.GetMultiBindingExpression
stattdessen die Methode verwendenBindingOperations.GetBindingExpression
.quelle
Das funktioniert bei mir:
quelle
Hier ganz elegant mit angehängten Verhaltensweisen beantwortet, meine bevorzugte Methode für fast alles.
WPF, wie Textfelder nach dem Drücken der Eingabetaste den Fokus verlieren
quelle
Ich persönlich halte eine Markup-Erweiterung für einen saubereren Ansatz.
quelle
Eine andere Lösung (nicht mit xaml, aber trotzdem ziemlich sauber, denke ich).
quelle