Вы можете реализовать подход на чистом XAML, создав прикрепленное поведение .
Что-то вроде этого:
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();
}
}
}
Затем в своем XAML вы устанавливаете InputBindingsManager.UpdatePropertySourceWhenEnterPressedProperty
свойство на то, которое вы хотите обновлять при Enterнажатии клавиши. Как это
<TextBox Name="itemNameTextBox"
Text="{Binding Path=ItemName, UpdateSourceTrigger=PropertyChanged}"
b:InputBindingsManager.UpdatePropertySourceWhenEnterPressed="TextBox.Text"/>
(Вам просто нужно обязательно включить ссылку на пространство имен xmlns clr для «b» в корневой элемент вашего файла XAML, указывающий на то, в какое пространство имен вы помещаете InputBindingsManager).
UpdatePropertySourceWhenEnterPressed
изменении действительного значения на другое действительное значение, вы без необходимости отказываетесь от подписки и повторно подписываетесь наPreviewKeyDown
событие. Вместо этого все, что вам нужно, это проверить, есть лиe.NewValue
этоnull
или нет. Если нетnull
, то подпишитесь; в противном случае еслиnull
, то отпишусь.Вот как я решил эту проблему. Я создал специальный обработчик событий, который вошел в код:
Затем я просто добавил это как обработчик событий KeyUp в XAML:
Обработчик событий использует свою
sender
ссылку для обновления собственной привязки. Поскольку обработчик событий является автономным, он должен работать в сложном DataTemplate. Этот единственный обработчик событий теперь можно добавить ко всем текстовым полям, которым нужна эта функция.источник
KeyBinding
в XAML для запуска этого метода, потому что в моем пользовательском интерфейсе есть элемент управления «По умолчанию», который улавливает клавишу ввода. Вам нужно поймать его в этом TextBox, чтобы остановить его распространение вверх по дереву пользовательского интерфейса до элемента управления «По умолчанию».Я не верю, что существует какой-либо "чистый XAML" способ сделать то, что вы описываете. Вы можете настроить привязку, чтобы она обновлялась всякий раз, когда текст в TextBox изменяется (а не когда TextBox теряет фокус), установив свойство UpdateSourceTrigger , например:
Если вы установите для UpdateSourceTrigger значение «Explicit», а затем обработаете событие TextBox PreviewKeyDown (ища клавишу Enter), то вы сможете добиться того, чего хотите, но для этого потребуется код программной части. Возможно, вам подойдет какое-то присоединенное свойство (похожее на мое свойство EnterKeyTraversal).
источник
Вы можете легко создать свой собственный элемент управления, унаследованный от TextBox, и повторно использовать его в своем проекте.
Что-то похожее на это должно работать:
Возможно, есть способ обойти этот шаг, но в противном случае вам следует выполнить привязку следующим образом (используя Explicit):
источник
Если вы объедините решения Ben и ausadmin, вы получите очень дружественное к MVVM решение:
... что означает, что вы передаете
TextBox
саму себя как параметр вCommand
.Это приводит к тому, что вы
Command
выглядите так (если вы используетеDelegateCommand
реализацию в стиле в своей виртуальной машине):Эта
Command
реализация может использоваться для любогоTextBox
кода, а лучше всего - без кода в коде программной части, хотя вы можете поместить его в собственный класс, чтобыSystem.Windows.Controls
в вашей виртуальной машине не было зависимостей . Это зависит от того, насколько строгие правила вашего кода.источник
Вот подход, который мне кажется довольно простым и более простым, чем добавление AttachedBehaviour (что также является допустимым решением). Мы используем UpdateSourceTrigger по умолчанию (LostFocus для TextBox), а затем добавляем InputBinding к клавише Enter, привязанной к команде.
Xaml выглядит следующим образом
Тогда методы Command
И TextBox привязан к свойству
Пока что это работает хорошо и улавливает событие Enter Key в TextBox.
источник
Это не ответ на исходный вопрос, а скорее продолжение принятого ответа @Samuel Jack. Я сделал следующее в собственном приложении и был поражен элегантностью решения Самуэля. Он очень чистый и многоразовый, так как его можно использовать с любым элементом управления, а не только с
TextBox
. Я подумал, что этим нужно поделиться с сообществом.Если у вас есть окно с тысячей,
TextBoxes
которые все требуют обновления источника привязки при вводе, вы можете связать это поведение со всеми из них, включив приведенный ниже XAML в свой,Window
Resources
а не прикрепляя его к каждому текстовому полю. Конечно, сначала вы должны реализовать прикрепленное поведение в соответствии с сообщением Самуэля .При необходимости вы всегда можете ограничить область видимости, поместив стиль в ресурсы одного из дочерних элементов окна (т.е. a
Grid
), который содержит целевые текстовые поля.источник
Если вы используете MultiBinding со своим TextBox, вам нужно использовать
BindingOperations.GetMultiBindingExpression
метод вместоBindingOperations.GetBindingExpression
.источник
Это работает для меня:
источник
Ответил здесь довольно элегантно, используя прикрепленные поведения, мой предпочтительный метод практически для всего.
WPF, как заставить текстовое поле терять фокус после нажатия клавиши ввода
источник
Я лично считаю, что наличие расширения разметки - более чистый подход.
источник
Другое решение (не использующее xaml, но все же довольно чистое, я думаю).
источник