An old problem with Silverlight TextBox is that it only updates its binding when the TextBox loses focus. This can cause a lot of problems, especially for LOB applications. Following a short discussion on Twitter with Rob Eisenberg (@EisenbergEffect), I tried to create a proof-of-concept behavior that can help ease this pain, at least until Silverlight gets an UpdateSourceTrigger that can handle the PropertyChanged value. (You can read more about the problem Rob had on Connect).
The behavior itself is very simple:
1: public class TextBoxUpdateBehavior : Behavior<TextBox>
2: {
3: protected override void OnAttached()
4: {
5: base.OnAttached();
6: AssociatedObject.TextChanged += AssociatedObjectOnTextChanged;
7: }
8:
9: private void AssociatedObjectOnTextChanged(object sender, TextChangedEventArgs args)
10: {
11: var bindingExpr = AssociatedObject.GetBindingBLOCKED EXPRESSION;
19: AssociatedObject.TextChanged -= AssociatedObjectOnTextChanged;
20: }
21: }
The key is in the TextChanged event handler. We simply get the Binding expression for the Text property of the TextBox, and call UpdateSource on it.
I tested the behavior with both UI-2-UI binding and with binding to a ViewModel. Both work flawlessly, and they even work at the same time as this screenshot shows:
As you can see, the cursor is still in the TextBox, so I have not moved the focus away after typing.
Here is the entire XAML:
1: <UserControl
2: xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3: xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4: xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
5: mc:Ignorable="d" xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity" xmlns:local="clr-namespace:SLTextBoxUpdateBinder" x:Class="SLTextBoxUpdateBinder.MainPage"
6: d:DesignWidth="640" d:DesignHeight="480">
7: <UserControl.DataContext>
8: <local:TestVM />
9: </UserControl.DataContext>
10: <Grid x:Name="LayoutRoot">
11:
12: <StackPanel>
13: <StackPanel Orientation="Horizontal">
14: <TextBlock Text="Binding using ViewModel: " Margin="10"/>
15: <TextBlock Text="{Binding TestProperty}" Margin="10" />
16: <Rectangle Fill="Black" Width="1" />
17: <TextBlock Text="Binding using UI-2-UI binding" Margin="10" />
18: <TextBlock Text="{Binding Text, ElementName=tb}" Margin="10" />
19: </StackPanel>
20: <StackPanel Orientation="Horizontal">
21: <TextBlock Text="Enter text here to see it shown above. No need to tab away!" Margin="10" />
22: <TextBox x:Name="tb" Text="{Binding TestProperty, Mode=TwoWay}" >
23: <i:Interaction.Behaviors>
24: <local:TextBoxUpdateBehavior/>
25: </i:Interaction.Behaviors>
26: </TextBox>
27: </StackPanel>
28: </StackPanel>
29: </Grid>
30: </UserControl>
I have attached the solution to this blog post. Marry Christmas everyone!
Posted
Dec 24 2009, 01:06 AM
by
vbandi