Jaime Rodriguez On Windows Phone, Windows Presentation Foundation, Silverlight and Windows 7
I am writing this tiny demo app, that has a TextBox data bound to a ViewModel. I want the TextBox to fire notifications to the ViewModel whenever the text changes (as opposed to only firing notifications when the textbox loses focus). In WPF, this is trivial to do, you just set the UpdateSourceTrigger on the Binding to PropertyChanged (in fact, I think that is the default). On the phone, I only see UpdateSourceTrigger supporting:
What to do? [12/5 (Update part 1) -- Updating this post due to enough feedback that the semantic of TextChanged is better than my post’s KeyUp. I did try that before suggesting KeyUp on my original post but I was seeing TextChanged fire more often than KeyUp (aka more times than I felt necessary). Now that I have seen there is no big perf hit (since others are doing it with TextChanged) I am back to proper semantics. Also you made me second guess and I tested on a keyboard and noticed that arrows can even the score firing KeyUp events.
How about:
Here are the snippets: In my XAML,
1: <TextBox x:Name="empIdTextBox" Text="{Binding Id, Mode=TwoWay, UpdateSourceTrigger=Explicit}"
2: TextChanged="empIdTextBox_TextChanged"/>
1: private void empIdTextBox_TextChanged(object sender, TextChangedEventArgs e)
2: {
3: TextBox box = (TextBox)sender;
4: BindingExpression be = box.GetBindingExpression(TextBox.TextProperty);
5: be.UpdateSource();
6:
7: }
1: public class UpdateSourceOnTextChangedBehavior : Behavior<TextBox>
3:
4: protected override void OnAttached()
5: {
6: base.OnAttached();
7: this.AssociatedObject.TextChanged += this.OnTextChanged;
8: }
9:
10: private void OnTextChanged(object sender, TextChangedEventArgs e)
11: {
12: BindingExpression be =
13: this.AssociatedObject.GetBindingExpression(TextBox.TextProperty);
14: be.UpdateSource();
15: }
16:
17: protected override void OnDetaching()
18: {
19: base.OnDetaching();
20: this.AssociatedObject.TextChanged -= this.OnTextChanged;
21: }
22: }
1: <TextBox x:Name="empIdTextBox" Grid.Column="1"
2: Text="{Binding Id, Mode=TwoWay,UpdateSourceTrigger=Explicit}" >
3: <interactivity:Interaction.Behaviors>
4: <local:UpdateSourceOnTextChangedBehavior />
5: </interactivity:Interaction.Behaviors>
6: </TextBox>
Hey Jaime, have you tried using the TextChanged event? That more literally matches your stated requirement. :) As for perf, you might retrieve the binding expression just once rather than with every change, assuming that fits your needs. I use a behavior that I built for PasswordBox that does pretty much the same thing.
You need to use a trigger and so bind the Update Source functionality to any event you want
Jaime, I didn't mean to suggest that you should be using a behavior--you did write "tiny demo app," after all. I did mean to suggest that the path you're heading down should work for you. :) Re .TextChanged firing more often than expected, possibly a bug?
The Behavior is so clean. It is mostly just "be.UpdateSource();". If you do another update perhaps you can show people how simple it is to consume the Behavior using Expression Blend :)