While there are useful answers here, IMHO none are really the best way. For me, the best and second-best options are:
- Fix the tab order so that there are focusable elements in the same focus scope as the
TextBox
both before and after the TextBox
in tab order. This is IMHO the best option, but it should be used only when this is a reasonable user interface choice. I.e. there already are UI elements that would naturally surround the TextBox
.
- Handle the
LostKeyboardFocus
event and explicitly update the binding then. Note that while the TextBox
hasn't lost focus in terms of the focus scope, it does always lose the keyboard focus if you tab out of it.
The second option looks like this:
<TextBox Text="{Binding SomeProperty}" LostKeyboardFocus="TextBox_LostKeyboardFocus"/>
private void TextBox_LostKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
{
BindingOperations.GetBindingExpression((DependencyObject)sender, TextBox.TextProperty)?.UpdateSource();
}
To elaborate:
The accepted answer defers updating the bound source property until some specific scenario (such as executing a "Save" command) that is known to need the property value occurs. Unfortunately, this negates one key benefits of the MVVM paradigm, which is one doesn't need to worry about when things happen per se, since the binding engine is supposed to take care of everything.
The highest-voted answer improves on this slightly, but as noted in the comments below it, it's still a scenario-specific solution. It would need to be applied for every element in the UI that has its own focus scope. But even worse is that it actually modifies the UI behavior for an element that is otherwise completely unrelated to the element we actually care about. Good coding practices mean fixing the original problem, rather than applying some unrelated change that just happens to have a side-effect that works in our favor.
If one can simply arrange the tab order in the UI such that there is an element in the same focus scope as the TextBox
that immediately follows the TextBox
, then IMHO that'd be the ideal solution. It means that the UI works predictably for the user and the code is aligned with the simplest implementation possible.
But this may not always be possible. In some cases, the natural tab order demands that the TextBox
is immediately preceded or followed by a Menu
, ToolBar
, or other element that is its own focus scope. In such cases, to me the most direct approach is simply to modify the "focus lost" behavior for the binding by explicitly handling the LostKeyboardFocus
event and updating the binding source when that event happens.