LostFocus (TextBox) vs. Buttons IsDefault-Property
Friday, May 2nd, 2008If you bind the Text-Property of a TextBox to something, the "something" is updated when the TextBox loses focus. This is the Default-UpdateSourceTrigger defined in the Metadata for the TextBox.TextProperty. In a Data Binding you can specify another UpdateSourceTrigger, like e.g. PropertyChanged.
If a TextBox has LostFocus as UpdateSourceTrigger, which is the default, you can get problems if the TextBox is inside of a Dialog that contains a OK-Button with the IsDefault-Property set to true. When the TextBox has the Focus, the user can press Enter and the Button is clicked, but the TextBox still keeps the Focus. The LostFocus-Event doesn’t occur, so the Source of a Data Binding isn’t updated with the value of the TextBoxs Text-Property. You need to update the source explicit. Let’s take an example and use the Person-class of my previous post:
public class Person : INotifyPropertyChanged { private string _name; public string Name { get { return _name; } set { _name = value; if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs("Name")); } } public event PropertyChangedEventHandler PropertyChanged; }
The Window below just contains a TextBox and a Button. The Text-Property of the TextBox is bound to the Name of the data in the DataContext. This would be a Person-instance, as you’ll see below in the codebehind-file. The Button has it’s IsDefault-Property set to true and defines an eventhandler for the Click-Event.
<Window x:Class="LostFocusTest.Window1" … xmlns:local="clr-namespace:LostFocusTest" Title="Focus/IsDefault" Width="200" SizeToContent="Height"> <StackPanel> <TextBox Margin="5" Text="{Binding Name}"/> <Button Content="OK" IsDefault="True" Click="Button_Click"/> </StackPanel> </Window>
In the Constructor in the Codebehind-file a Person-instance is created. It’s assigned to the Windows DataContext-Property, so the TextBox above will display the Persons name, which is set to "Thomas". The Click-Eventhandler for the Button simply displays the name of the Person in a MessageBox.
public partial class Window1 : Window { private Person _pers; public Window1() { InitializeComponent(); _pers = new Person(); _pers.Name = "Thomas"; this.DataContext = _pers; } private void Button_Click(object sender, RoutedEventArgs e) { MessageBox.Show(_pers.Name); } }
If I start the application and type "Urs" into the TextBox and press Enter, the Button is clicked but the TextBox keeps the focus. So the Source, which is the Person-Instance, isn’t updated and the MessageBox still displays the old value (”Thomas”), as you can see in the Image below:

For such a scenario, you have to update the source explicit. You could do this in the Click-Eventhandler. To update the source, you have to get the BindingExpression for the TextProperty. You get the BindingExpression by calling the GetBindingExpression-Method on the TextBox. Pass in the Text-Property as parameter. On the BindingExpression call the UpdateSource-Method to update the Person-instance explicitly with the value defined in the Text-Property of the TextBox. With the Eventhandler below the Person-Instance would always be actualized when the Button is clicked. The MessageBox would display the right value:
private void Button_Click(object sender, RoutedEventArgs e) { TextBox textBox = Keyboard.FocusedElement as TextBox; if (textBox != null) { BindingExpression be = textBox.GetBindingExpression(TextBox.TextProperty); if (be != null) be.UpdateSource(); } MessageBox.Show(_pers.Name); }
Just kick it for me:


