Search code examples
c#silverlightasynchronoustextboxtextchanged

How to make Silverlight TextBox.TextChanged event fire synchronously?


Platform: Silverlight 4 / .NET 4

Description:

I have a ComboBox, a Textbox and a NumericUpDown.

<StackPanel Margin="10">
    <ComboBox SelectionChanged="cmbChanged" Margin="3">
        <ComboBoxItem Content="A" />
        <ComboBoxItem Content="B" />
    </ComboBox>
    <TextBox x:Name="txt" TextChanged="txtChanged" Margin="3"/>
    <CheckBox x:Name="chk" Checked="chkChecked" Unchecked="chkChecked" Content="Check box" Margin="3"/>
    <ListBox x:Name="lst" Height="100" Margin="3"/>
</StackPanel>

A list is for debugging purposes.

Repro:

Note that there are event handlers for TextBox.TextChanged, CheckBox.Checked, CheckBox.Unchecked and ComboBox.SelectionChanged.

Here are the handlers:

private void cmbChanged(object sender, SelectionChangedEventArgs e)
{
    lst.Items.Clear();
    txt.Text = (sender as ComboBox).SelectedIndex.ToString();
    chk.IsChecked = !chk.IsChecked;
}

private void txtChanged(object sender, TextChangedEventArgs e)
{
    lst.Items.Add("Text Changed");
}

private void chkChecked(object sender, RoutedEventArgs e)
{
    bool? chk = (sender as CheckBox).IsChecked;
    lst.Items.Add("CheckBox Changed to " + chk);
}

Problem:

In the combobox's event handler, I set the text in the textbox BEFORE setting the check state of the checkbox. However, if you take a look at the picture below, you will see that the event handler for the CheckBox.Checked gets called before TextBox.TextChanged.

TextBox.TextChanged occurs asynchronously

The problem is obviously in the asynchronous execution of the TextBox.TextChanged event, as stated in the MSDN definition:

The TextChanged event is asynchronous. The event cannot be canceled.

I really need these event handlers to execute exactly in the order they are changed.

Question: Is there any simple way to achieve what I need?


Solution

  • Perhaps it might be better to call your piece of business logic directly, instead of relying on the event handlers. You can always remove and add the EventHandler in case you don't want to hit that trigger in your particular situation:

    //Remove event handlers:
    CheckBox.Checked -= chkChecked;
    TextBox.TextChanged -= txtChanged;
    
    //Call your business stuff here
    
    //You can also 'safely' set values on your textbox and 
    //checkbox since they wont trigger events now.
    
    //Re-add event handlers, so they react on user input again:
    CheckBox.Checked += chkChecked;
    TextBox.TextChanged += txtChanged;