Data binding does not update the property when you press Enter in the dialog with the default button

My settings are described below:

  • WPF 4 Application
  • MVVM Lite Structure
  • The "Add item" window is displayed on top of the main window in dialog mode (using view.ShowDialog ();)
  • The dialog box has several input fields, and the Save button, which has the IsDefault property, is set to True
  • The save button is processed using command binding
  • Data binding is defined between input fields in the XAML field of view and the corresponding properties in the ViewModel (one way, for the user interface to update the ViewModel using = OneWayToSource mode)

The problem is that when I press Enter on the keyboard, the value that I provided in the last input field does not fall into the base ViewModel property.

I suspect that this is because the input field did not lose focus before closing the window (and thus all the bindings are β€œdissolved”). For comparison, if I click the "Save" button (instead of allowing the click to be processed by the window on Enter), the value will be updated in the property. Moreover, if I add (horror! Horror!) An event handler to the Click event button and the call button .Focus () in the code, everything works!

What could be the medicine?

Obviously, I do not want to handle any window closing events and manually extract missing values ​​... This will violate the whole concept of MVVM :-(

Any best deals?

Thanks Alex

+7
source share
4 answers

By default, a TextBox notifies only the source that changed its value after losing focus. You can change this in your binding by setting UpdateSourceTrigger=PropertyChanged . This will cause the TextBox to send an update notification to its source, and the text will be changed, and not just when it loses focus.

If you do not want to send an update notification at any time you press a key, you can create an AttachedProperty to update the source if the Enter key is pressed.

Here is the AttachedProperty that I use for situations like this:

 // When set to True, Enter Key will update Source #region EnterUpdatesTextSource DependencyProperty // Property to determine if the Enter key should update the source. Default is False public static readonly DependencyProperty EnterUpdatesTextSourceProperty = DependencyProperty.RegisterAttached("EnterUpdatesTextSource", typeof (bool), typeof (TextBoxHelper), new PropertyMetadata(false, EnterUpdatesTextSourcePropertyChanged)); // Get public static bool GetEnterUpdatesTextSource(DependencyObject obj) { return (bool) obj.GetValue(EnterUpdatesTextSourceProperty); } // Set public static void SetEnterUpdatesTextSource(DependencyObject obj, bool value) { obj.SetValue(EnterUpdatesTextSourceProperty, value); } // Changed Event - Attach PreviewKeyDown handler private static void EnterUpdatesTextSourcePropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e) { var sender = obj as UIElement; if (obj != null) { if ((bool) e.NewValue) { sender.PreviewKeyDown += OnPreviewKeyDownUpdateSourceIfEnter; } else { sender.PreviewKeyDown -= OnPreviewKeyDownUpdateSourceIfEnter; } } } // If key being pressed is the Enter key, and EnterUpdatesTextSource is set to true, then update source for Text property private static void OnPreviewKeyDownUpdateSourceIfEnter(object sender, KeyEventArgs e) { if (e.Key == Key.Enter) { if (GetEnterUpdatesTextSource((DependencyObject) sender)) { var obj = sender as UIElement; BindingExpression textBinding = BindingOperations.GetBindingExpression( obj, TextBox.TextProperty); if (textBinding != null) textBinding.UpdateSource(); } } } #endregion //EnterUpdatesTextSource DependencyProperty 
+12
source

Try it.

{Binding Property, UpdateSourceTrigger = PropertyChanged, Mode = OneWayToSource}

+3
source

A simple trick is moving the focus away from the control, for example. to the button itself. You can do this in the button's Click handler, as it will be executed before the associated command:

  public MyView() { InitializeComponent(); _button.Click += delegate { _button.Focus(); }; } 

If you do not like the code in your view, you can also do this in the behavior that you add to your button.

0
source

This is just a WPF bug. (Design or implementation, I do not know.) Updating a TextBox in case of loss of focus is the expected behavior in most cases, and also the default button should work in dialogs.

For a workaround, I think this is the wrong direction to like with TextBox. The best solution is to force the focus to click the default button.

-3
source

All Articles