Skip to main content

Answered Question Why is TextChanged event for TextBox called BEFORE the ViewModel is updated (via TwoWay binding)? Now the EventHandler concludes nothing is changed!RSS Feed

(0)

marcschluper
marcschl...

Member

Member

38 points

39 Posts

Why is TextChanged event for TextBox called BEFORE the ViewModel is updated (via TwoWay binding)? Now the EventHandler concludes nothing is changed!

I have a DataGrid that shows items and a details form that allows editing of individual items. (Editing in the grid itself makes accidental changes more likely.) I have a Save button that updates the data. This Save button is only enabled if the data has been changed.

I tried to accomplish this via TwoWay binding. Unfortunately the events are not handled in the order that suits my needs. Am I doing something wrong?

The core code (DataContext = ViewModel):

        void PeopleGrid_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            Person selectedPerson = PeopleGrid.SelectedItem as Person;
            ViewModel.CurrentPersonIndex = PeopleGrid.SelectedIndex;
            ViewModel.CurrentPerson = selectedPerson.Copy();
        }
       
...

    public class Person : IComparable, INotifyPropertyChanged
    {
        private string _name;
        public string Name
        {
            get { return _name; }
            set
            {
                if (_name != value)
                {
                    _name = value;
                    if (PropertyChanged != null)
                    {
                        PropertyChanged(this, new PropertyChangedEventArgs("Name"));
                    }
                }
            }
        }
       
...

        NameTextBox.TextChanged += new TextChangedEventHandler(NameTextBox_TextChanged);

...

        void NameTextBox_TextChanged(object sender, TextChangedEventArgs e)
        {
            AdjustSaveButton();
        }

        private void AdjustSaveButton()
        {
            Person originalPerson = ViewModel.People[ViewModel.CurrentPersonIndex];
            SaveButton.IsEnabled = (originalPerson.CompareTo(ViewModel.CurrentPerson) > 0);
        }
       
       
       
Some related XAML:

    <data:DataGrid x:Name="PeopleGrid" ItemsSource="{Binding People}" />

    <TextBox x:Name="NameTextBox" Text="{Binding CurrentPerson.Name, Mode=TwoWay}" />
   
   
The problem I face is that AdjustSaveButton() is called BEFORE the Name setter and hence SaveButton.IsEnabled remains false upon the first change in the NameTextBox. Upon the second change the setter has been called once, and hence SaveButton.IsEnabled is set to true. That's obviously one key stroke too late ...

 Thanks!

Marc Schluper

Klinger
Klinger

Participant

Participant

1686 points

300 Posts

Answered Question

Re: Why is TextChanged event for TextBox called BEFORE the ViewModel is updated (via TwoWay binding)? Now the EventHandler concludes nothing is changed!

I have had this issue before too. The actual binding happens only after the TextChanged event handler is executed.

What makes sense to me now that I understand it better.

You can do the following to force the binding to happen:

            var tb = sender as TextBox;
            var be = tb.GetBindingExpression(TextBox.TextProperty);
            if (be != null)
            {
                be.UpdateSource();
            }

            AdjustSaveButton();

Klinger

marcschluper
marcschl...

Member

Member

38 points

39 Posts

Re: Why is TextChanged event for TextBox called BEFORE the ViewModel is updated (via TwoWay binding)? Now the EventHandler concludes nothing is changed!

Thanks  you! Are you sure this applies to Silverlight? On the Internet I see GetBindingExpression in the context of WPF but not Silverlight.

You would do me a favor if you elaborated on why it makes sense that the binding happens only after the TextChanged event handler is executed. In my scenario that does not seem to be helpful. Or maybe I should take a different approach?

Marc Schluper

Klinger
Klinger

Participant

Participant

1686 points

300 Posts

Re: Why is TextChanged event for TextBox called BEFORE the ViewModel is updated (via TwoWay binding)? Now the EventHandler concludes nothing is changed!

Yes, it works on Silverlight.

Regarding the TextChanged event.

The way I see TextChanged event is independent of the binding itself.

TextChanged means that the control property Text has changed.

It may ot may not have a binding expression attached to it.

And, because you know that the text has been changed we can all sort of

things just before the binding is actually executed.

Maybe we are missing an event here. BindingExecuted?

This behavior does not goes well with MVVM I have to agree.

Klinger

marcschluper
marcschl...

Member

Member

38 points

39 Posts

Re: Why is TextChanged event for TextBox called BEFORE the ViewModel is updated (via TwoWay binding)? Now the EventHandler concludes nothing is changed!

Must be Silverlight 3 then. Will check solution at home tonight. Thanks!

Marc Schluper

brauliod
brauliod

Participant

Participant

1307 points

502 Posts

Silverlight MVP

Re: Why is TextChanged event for TextBox called BEFORE the ViewModel is updated (via TwoWay binding)? Now the EventHandler concludes nothing is changed!

Well.. encapsulated in a user control the workaround...

public class TextBoxChangeExt : System.Windows.Controls.TextBox

{

public TextBoxChangeExt()

{

this.TextChanged += new TextChangedEventHandler(TextBoxChangeExt_TextChanged);

}

void TextBoxChangeExt_TextChanged(object sender, TextChangedEventArgs e)

{

// based on

// http://betaforums.silverlight.net/forums/t/103695.aspx

TextBox txCtl = (TextBox)sender;if (txCtl != null)

{

var be = txCtl.GetBindingBLOCKED EXPRESSION

{

be.UpdateSource();

}

}

}

}

// ---------------------------------
    Braulio Diez

    http://www.dbschemaeditor.com
    Free Silverlight Based Database Schema Editor
/// ---------------------------------
  • Unanswered Question
  • Answered Question
  • Announcement