TextBox skipping every other "set" when appending.
I have a Silverlight 2.0 user control containing a two-way bound TextBox. It is bound to a CLR property on an object that implements INotifyPropertyChanged. The text box is not calling my property setter every time the text box is edited. It appears to skip every other edit.
The way in which I fire PropertyChanged is unusual and appears to be related to the bug. I use the DispatcherSynchronizationContext to delay the event. I am using this technique to queue update notifications until after all changes have taken place. This technique works well in WPF. When I comment out this code and instead fire the event directly, Silverlight also works. I would like to be able to use this technique within Silverlight.
To reproduce the problem, enter the text "a" in the first text box and tab out. Then go back to the first text box and append a "b" and tab out. The first text box will show "ab" but the others will show "a". Then go back again and append a "c". Now all three show "abc". If you select and replace parts of the text, the problem does not occur.
Thank you for your help.
Here is the source code:
Document.cs
using System.ComponentModel;
using System.Threading;
using System.Windows.Threading;
namespace SLBindingSetterBug
{
public class Document : INotifyPropertyChanged
{
private static SendOrPostCallback _callback = new SendOrPostCallback(TriggerUpdate);
private static void TriggerUpdate(object obj)
{
Document p = (Document)obj;
p.FirePropertyChanged("MyText");
}
public event PropertyChangedEventHandler PropertyChanged;
private string _myText;
public string MyText
{
get
{
return _myText;
}
set
{
_myText = value;
DispatcherSynchronizationContext.Current.Post(_callback, this);
}
}
private void FirePropertyChanged(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
}
Page.xaml
<UserControl x:Class="SLBindingSetterBug.Page"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="400" Height="300">
<Grid x:Name="LayoutRoot" Background="White">
<StackPanel>
<TextBox Text="{Binding MyText, Mode=TwoWay}" />
<TextBox Text="{Binding MyText, Mode=TwoWay}" />
<TextBlock Text="{Binding MyText}" />
</StackPanel>
</Grid>
</UserControl>
Page.xaml.cs
using System.Windows.Controls;
namespace SLBindingSetterBug
{
public partial class Page : UserControl
{
public Page()
{
InitializeComponent();
DataContext = new Document();
}
}
}
Michael L Perry
http://adventuresinsoftware.com/blog