views:

188

answers:

1

I'm trying to validate a UI change when Enter key is pressed. The UI element is a textbox, which is data binded to a string. My problem is that the data binding hasn't updated TestText when Enter key is Up. It is only updated when I press the button which brings up a message box.

/// <summary>
/// Interaction logic for Window1.xaml
/// </summary>
public partial class Window1 : Window, INotifyPropertyChanged
{
    String _testText = new StringBuilder("One").ToString();
    public string TestText
    {
        get { return _testText; }
        set { if (value != _testText) { _testText = value; OnPropertyChanged("TestText"); } }
    }


    public Window1()
    {
        InitializeComponent();
        myGrid.DataContext = this;
    }

    private void OnPropertyChanged(string property)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(property));
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    private void onKeyUp(object sender, KeyEventArgs e)
    {
       if (e.Key != System.Windows.Input.Key.Enter) return;
       System.Diagnostics.Trace.WriteLine(TestText);
    }

    private void button1_Click(object sender, RoutedEventArgs e)
    {
        MessageBox.Show(TestText);
    }

}

Window XAML:

Window x:Class="VerificationTest.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300" KeyUp="onKeyUp"

TextBox XAML:

TextBox Name="myTextBox" Text="{Binding TestText}"

Button XAML:

Button Name="button1" Click="button1_Click"
+1  A: 

In order to force the TextBox to commit the value back to the binding source you can do:

var binding = myTextBox.GetBindingExpression(TextBox.TextProperty);
binding.UpdateSource();

Optionally, you can configure the binding to update the source every time the Text property changes which would mean on every character you enter into the text box.

<TextBox Name="myTextBox"
         Text="{Binding TestText, UpdateSourceTrigger=PropertyChanged}" />

But this will raise a lot of property change notifications. What I have done in my applications was to create a class derived from TextBox to override the OnKeyDown method and when enter is pressed, I call the UpdateSource method as I described above and also call SelectAll on the TextBox to give the user an idea that I just "accepted" their input. Deriving a class from TextBox will let you reuse that behavior anywhere else you might want it in your application.

Josh Einstein
Thanks... it works for my simple demo case. Any tip on how to force the update if I have many UI elements like this?
Martin
Refer to my edits. I just added a suggestion to create a class derived from TextBox. There's about a dozen ways you could do it in WPF using behaviors, attached dependency properties, commands, etc but I think doing it in a derived class the way I suggested would be the easiest approach.
Josh Einstein