Możesz stworzyć podejście oparte na czystym XAML, tworząc dołączone zachowanie .
Coś takiego:
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();
}
}
}
Następnie w XAML ustawiasz InputBindingsManager.UpdatePropertySourceWhenEnterPressedProperty
właściwość na tę, którą chcesz zaktualizować po Enternaciśnięciu klawisza. Lubię to
<TextBox Name="itemNameTextBox"
Text="{Binding Path=ItemName, UpdateSourceTrigger=PropertyChanged}"
b:InputBindingsManager.UpdatePropertySourceWhenEnterPressed="TextBox.Text"/>
(Musisz tylko upewnić się, że zawiera odwołanie do przestrzeni nazw clr xmlns dla „b” w elemencie głównym pliku XAML, wskazując na przestrzeń nazw, w której umieścisz InputBindingsManager).
UpdatePropertySourceWhenEnterPressed
zmienia się z prawidłowej wartości na inną,PreviewKeyDown
niepotrzebnie anulujesz subskrypcję i ponownie subskrybujesz wydarzenie. Zamiast tego wystarczy sprawdzić, czy take.NewValue
jest,null
czy nie. Jeśli nienull
, zapisz się; w przeciwnym razienull
zrezygnuj z subskrypcji.W ten sposób rozwiązałem ten problem. Stworzyłem specjalny program obsługi zdarzeń, który wszedł do kodu za:
Następnie właśnie dodałem to jako program obsługi zdarzeń KeyUp w XAML:
Procedura obsługi zdarzeń używa swojego
sender
odwołania, aby spowodować zaktualizowanie własnego powiązania. Ponieważ program obsługi zdarzeń jest niezależny, powinien działać w złożonym DataTemplate. Ten jeden program obsługi zdarzeń można teraz dodać do wszystkich pól tekstowych, które wymagają tej funkcji.źródło
KeyBinding
w języku XAML do uruchomienia tej metody, ponieważ mój interfejs użytkownika ma kontrolkę „Default”, która przechwytuje klawisz Enter. Musisz go przechwycić w tym TextBox, aby zatrzymać propagację drzewa interfejsu użytkownika do kontrolki „Default”.Nie wierzę, że istnieje „czysty XAML” sposób na zrobienie tego, co opisujesz. Możesz skonfigurować powiązanie, aby było aktualizowane za każdym razem, gdy zmieni się tekst w TextBox (zamiast gdy TextBox utraci fokus), ustawiając właściwość UpdateSourceTrigger , na przykład:
Jeśli ustawisz UpdateSourceTrigger na „Explicit”, a następnie obsłużysz zdarzenie PreviewKeyDown TextBox (szukając klawisza Enter), możesz osiągnąć to, co chcesz, ale wymagałoby to użycia kodu. Może jakiś załączonym własności (podobny do mojego EnterKeyTraversal mienia) pracy woudld dla Ciebie.
źródło
Możesz łatwo utworzyć własną kontrolkę dziedziczącą po TextBox i używać jej ponownie w całym projekcie.
Coś podobnego powinno działać:
Może istnieć sposób na obejście tego kroku, ale w przeciwnym razie powinieneś połączyć się w ten sposób (używając jawnego):
źródło
Jeśli połączysz rozwiązania Bena i ausadmin, otrzymasz rozwiązanie bardzo przyjazne dla MVVM:
... co oznacza, że przekazujesz
TextBox
siebie jako parametr doCommand
.Prowadzi to do tego, że
Command
wyglądasz tak (jeśli używaszDelegateCommand
implementacji w stylu A w swojej maszynie wirtualnej):Ta
Command
implementacja może być używana dla dowolnego,TextBox
a co najważniejsze, bez kodu w kodzie, chociaż możesz chcieć umieścić to w swojej własnej klasie, aby nie było żadnych zależności naSystem.Windows.Controls
Twojej maszynie wirtualnej. Zależy to od tego, jak surowe są wytyczne dotyczące kodu.źródło
Oto podejście, które wydaje mi się dość proste i łatwiejsze niż dodanie AttachedBehaviour (które jest również prawidłowym rozwiązaniem). Używamy domyślnego UpdateSourceTrigger (LostFocus for TextBox), a następnie dodajemy InputBinding do klawisza Enter, powiązanego z poleceniem.
XAML wygląda następująco
Następnie metody Command są
TextBox jest powiązany z Property
Jak dotąd wydaje się, że działa to dobrze i przechwytuje zdarzenie Enter Key w TextBox.
źródło
To nie jest odpowiedź na pierwotne pytanie, ale raczej rozszerzenie zaakceptowanej odpowiedzi @Samuel Jack. Zrobiłem co następuje we własnej aplikacji i byłem pod wrażeniem elegancji rozwiązania Samuela. Jest bardzo czysty i nadaje się do wielokrotnego użytku, ponieważ można go używać na dowolnym sterowaniu, nie tylko
TextBox
. Pomyślałem, że należy się tym podzielić ze społecznością.Jeśli masz okno z tysiącem,
TextBoxes
które wszystkie wymagają zaktualizowania źródła powiązania w Enter, możesz dołączyć to zachowanie do wszystkich, włączając poniższy kod XAML do swojego,Window
Resources
zamiast dołączać go do każdego TextBox. Najpierw musisz oczywiście zaimplementować załączone zachowanie zgodnie z postem Samuela .W razie potrzeby zawsze możesz ograniczyć zakres, umieszczając styl w zasobach jednego z elementów potomnych okna (tj. A
Grid
), który zawiera docelowe pola tekstowe.źródło
Jeśli używasz MultiBinding z TextBox, musisz użyć
BindingOperations.GetMultiBindingExpression
metody zamiastBindingOperations.GetBindingExpression
.źródło
To działa dla mnie:
źródło
Odpowiedziałem tutaj dość elegancko, używając przywiązanych zachowań, mojej preferowanej metody na prawie wszystko.
WPF, jak sprawić, by pole tekstowe straciło fokus po naciśnięciu klawisza Enter
źródło
Osobiście uważam, że posiadanie rozszerzenia znaczników jest czystszym podejściem.
źródło
Inne rozwiązanie (nie używam xaml, ale myślę, że nadal jest całkiem czysty).
źródło