Better way to update bound controls when changing the datasource

12,381

It's not a whole lot better, using Binding.ReadValue might save the hassle of unbinding and rebinding, assuming the object you are binding to remains the same:

foreach (Control c in pnlBody.Controls)
    foreach (Binding b in c.DataBindings)
        b.ReadValue();

If, on the other hand, you are changing the underlying bound object, this will not work. I suggest putting a BindingSource between the Bindings and the Row object, this way you only have to re-bind the binding source and not all 50 bindings individually. Either by a call to BindingSource.CancelEdit() or by resetting the data source:

RowBindingSource.DataSource = null;
RowBindingSource.DataSource = this.Row;
Share:
12,381

Related videos on Youtube

Nevyn
Author by

Nevyn

Been doing C# Application Development for around 6 years now. Working mostly with Winforms and .NET. I have also done some basic work with ASP.NET using a C# code base.

Updated on September 15, 2022

Comments

  • Nevyn
    Nevyn almost 2 years

    The problem. I have a databinding to the fields within a property on my form for a large number of textboxes on the form itself. I am changing not just a field value within the property, but the entire property (resetting to a previously saved default).

    What I wanted to do was something like this:

    ((CurrencyManager)BindingContext[Row]).Refresh();
    

    Doesn't work, BindingContext[Row] is a PropertyManager, not a CurrencyManager, and doesn't have a refresh method. PushData() is protected and not accessable. I also tried calling this.Refresh(), and individually on each control I tried calling c.Refresh...Now What?

    Here's the code Im currently using:

    private void btnReset_ButtonClicked(object sender, EventArgs e)
    {
        Row = ResetRow.Clone();//use clone to break the reference, dont want to be updating the ResetRow when Row fields change.
    
        foreach (Control c in pnlBody.Controls)
            if (c.DataBindings.Count > 0)
                c.DataBindings.Clear();
    
        DataBindandSet();//re-apply all the databindings (50)
    }
    
    //just a sample of the databinding function itself
    private void DataBindandSet()
    {
        txtAzimuth.DataBindings.Add(new NullableBinding("Text", Row, "Azimuth", true));
        txtBHTemp.DataBindings.Add(new NullableBinding("Text", Row, "BHTemp", true));
        //repeat 48 more times
    }
    

    Update I set the databindings to the full databinding string, to see if setting the null value default had any effect, it didnt.

    txtAzimuth.DataBindings.Add(new NullableBinding("Text", Row, "Azimuth", true, DataSourceUpdateMode.OnPropertyChanged, ""));
    

    Row is a public property on the form itself. ResetRow is a private property on the form, its assigned to a clone of the initial row on Form Load and never changed, it serves as a backup. The value of some of the properties (but not all) is allowed to be null, and should display as an empty string. This is what the NullableBinding class does behind the scenes

    Can anyone think of a better way to do this than removing and re-applying every single one of the databindings?

  • Nevyn
    Nevyn over 11 years
    I have no idea why, because that looks great on paper....but it isn't updating the textbox. Good thought though, and more efficient, if only slightly, than clearing and rebinding everything.
  • lc.
    lc. over 11 years
    @Nevyn Just a thought but is the textbox a direct child of pnlBody?
  • Nevyn
    Nevyn over 11 years
    Yes, all the bound controls are inside pnlBody. The form itself has also has pnlHeader and some buttons and side panels. That's also why im checking c.Databindings.Count, because the textboxes have some labels beside them that I dont really care about.
  • lc.
    lc. over 11 years
    @Nevyn Re-reading your question I understand you are changing the object Row points to? If so I think the binding still keeps the reference to the old object, which is why this doesn't work. I'd try putting a BindingSource between the bindings and the Row object.
  • Nevyn
    Nevyn over 11 years
    still doesn't seem to work. Tried BindingSource.CurrencyManager.Refresh() and BindingSource.ResetBindings(). Refuses to update the data in the textboxes.
  • lc.
    lc. over 11 years
    @Nevyn I think you have to re-bind the BindingSource if you change the bound object (BindingSource.DataSource = null; BindingSource.DataSource = Row;). But it's now down to one place instead of 50.
  • Nevyn
    Nevyn over 11 years
    Pretty close. I rethought it slighty. Refresh and Reset didn't work, but BindingSource treats the property like a List Entry...BindingSource.CancelEdit() looks like it works just fine. I might not even have to save a copy of the row for that to work...I will accept this as the answer, although I encourage you to edit the answer to what it actually is, rather than what you have up there :-)
  • lc.
    lc. over 11 years
    @Nevyn Ok, edited. If you have more to add you can either comment or even just put your own answer with what you got to work and accept that instead :)
  • Michael Murphy
    Michael Murphy almost 9 years
    ControlBindingSource.DataSource = null; Did not work for me.
  • ProfK
    ProfK over 7 years
    Because everybody always binds their forms to DataTables. Those are history by now, my friend.