Horrible databinding performance

Hi,

I have a form with 40 databound controls. The controls (mostly TextBoxes etc.) are connected to data model that implements INotifyPropertyChanged. The problem we face is that each control is pushed data when a single data model property changes. This is a significant problem during initialization when all the properties are set, causing 40 x 40 =1600 getter calls, but it's a problem in normal property usage, too, if some properties must be fetched from database instead of private member.

I have tried to counter this problem by using some block operations that internally do not use properties, but private members etc. This doesn't really work anymore because I need to use robust and simple interface from now on without these optimized block operations.

Is there any way to use DataBinding with INotifyPropertyChanged without this overhead of redundant getter calls

-Kimmo



Answer this question

Horrible databinding performance

  • bharath-k

    Not sure I understand the problem. A few questions, if you don't mind:

    1. Why is it that "each control is pushed data when a single data model property changes" For example, if a single textbox control is bound to a single property, then when that property changes, the data would only get pushed to that single control and no other controls would be involved, correct

    2. What is happening during initialization, that the 40 controls get initialized 40 times each

    3. As each property is changed, you raise the PropertyChanged event specifying the sepcific (and only the specific) property that changed, correct

    Almost sounds like you are raising PropertyChanged but NOT specifying any property, which is the equivalent of indicating that ALL properties have changed. For example doing something like:

    RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(""))

    instead of

    RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("PropertyName"))


  • papercodes

    Kimmock:

    What do you make of this in the product feedback center

    https://connect.microsoft.com/feedback/viewfeedback.aspx FeedbackID=115342&wa=wsignin1.0&siteid=210

    Seems contrary to our wishes.


  • DRCH

    Matty4242 wrote:

    https://connect.microsoft.com/feedback/viewfeedback.aspx FeedbackID=115342&wa=wsignin1.0&siteid=210

    Seems contrary to our wishes.



    Interesting. I tried to reproduce that problem and it's related to BindingSource somehow. If I bind the properties of datamodel directly to GUI controls (without BindingSource), the problem disappears.

    In any case, I hope Microsoft fixes both problems. If someone really wanted all the controls to be refreshed when a single property changes, he could just simply call PushData. But for our problem (all inrelevant controls are pushed data) there is no general workaround to my knowledge.

    -Kimmo

  • cgrinton

    It appears that everything you are doing is correct, at least in my limited experience opinion.  And I have replicated the problem you are referring to and I am a little surprised.  Also, I have noticed that when I bind the GetterCount to the label, the label gets updated even though I do not raise the PropertyChanged event in the GetterCount property setter of my sample appllication - this suggests that it is being updated from somewhere else other than the Person object (most likley something to do with the form or the fact that the same data source is being used within some context).

    I would suggest searching the product feedback site (http://connect.microsoft.com/feedback/default.aspx SiteID=210) to see if there is a defect listed in this area - I would do it, but cannot today.

     

    Woops - found it anyway - http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx FeedbackID=207223

     


  • Octavio

    Matty4242 wrote:

    Not sure I understand the problem. A few questions, if you don't mind:

    1. Why is it that "each control is pushed data when a single data model property changes" For example, if a single textbox control is bound to a single property, then when that property changes, the data would only get pushed to that single control and no other controls would be involved, correct

    That's what I expected, too, but that's not the case! I was so puzzled when I realized this that I needed to use Reflector to check this behaviour from the sources (I'm using 2.0 framework, btw).

    I'm using a simple test class "Person" with 3 properties, like (only one property shown here)

    public event PropertyChangedEventHandler PropertyChanged;

    private void NotifyPropertyChanged(String info)
    {
    if (PropertyChanged != null)
    {
    PropertyChanged(this, new PropertyChangedEventArgs(info));
    }
    }

    private string firstName;
    public string FirstName
    {
    get
    {
    getterCount++;
    return (this.firstName);
    }
    set
    {
    if (this.firstName != value)
    {
    this.firstName = value;
    NotifyPropertyChanged("FirstName");
    }
    }
    }

    Notice the getterCount memeber that is initialized. It counts each getter call of the 3 properties. In the form I have the following code:

    public partial class Form1 : Form
    {
    private Person person = new Person();
    public Form1()
    {
    InitializeComponent();

    textBox1.DataBindings.Add("Text", person, "FirstName");
    textBox2.DataBindings.Add("Text", person, "FamilyName");
    textBox3.DataBindings.Add("Text", person, "Age");
    label1.DataBindings.Add("Text", person, "GetterCount");
    }

    private void button1_Click(object sender, EventArgs e)
    {
    person.FirstName = "A";
    person.FamilyName = "B";
    person.Age = 35;
    }
    }

    When the form is first shown, getterCount = 3. After clicking button1, the count = 12. The increase in 9, which is 3*3;

    Matty4242 wrote:

    3. As each property is changed, you raise the PropertyChanged event specifying the sepcific (and only the specific) property that changed, correct

    Almost sounds like you are raising PropertyChanged but NOT specifying any property, which is the equivalent of indicating that ALL properties have changed. For example doing something like:

    RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(""))

    instead of

    RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("PropertyName"))



    I'm doing this correctly. See the sample property above in my code.

  • NetPochi

    I believe we know for a fact that the data from unrelated object properties are being gotten (Get accessor) unnecessarily, but, do we really know for a fact that the UI Controls are being pushed data unnecessarily That is, how can we measure how many times the text of a textbox is being set. I don't think we can use the TextChanged event because if the data is being pushed unnecessarily, then the textbox text is not actually changing and so the event won't fire.

    So I created my own User Control that is basically the same as a TextBox just wrapped so that I can interrogate the Property Text Set routine and sure enough, it looks like not only is the Data Object Property Get routine being called unnecessarily, but also the UI Control Property Set routine is being called unnecessarily, for example, repeatedly setting the Text to the same Text that was previously set because some other data object property has changed.

    I know this isn't good news, but I wanted to document somewhere how I confirmed this.

    ... How difficult could it be to rewrite DataBinding


  • Horrible databinding performance