Binding errors disposing forms?

Binding errors disposing forms?

Old forum URL: forums.lhotka.net/forums/t/166.aspx


ajj3085 posted on Monday, May 22, 2006

Hi all,

I'm having a weird problem.

I have two NameValueList classes, and each list is accessed as a Singleton.

I bind each list to the DataSource of a ComboBox.  I also bind the ComboBox's text property to a BO string property.

When the BO is saved, my data code checks the list.  If the value the user typed in the combo box does not exist in the singleton list, some data code fires to insert the new item and get the new id back for the item.  The data code then calls an internal method to add this new item to the static list.

Everything works fine.  The save returns, I check the Singleton lists and the new values are there.  the problem is when the form closes, and starts Disposing controls.  I get this message:

Message: ArgumentException: Cannot bind to the property or column State on the DataSource.
Parameter name: dataMember

State is the name of the propery on my BO.  The DataSource is bound to a BindingSource, who's datasource is the singleton list.

Here's a stack trace:
tack trace:    at System.Windows.Forms.BindToObject.CheckBinding()
   at System.Windows.Forms.BindToObject.SetBindingManagerBase(BindingManagerBase lManager)
   at System.Windows.Forms.Binding.SetListManager(BindingManagerBase bindingManagerBase)
   at System.Windows.Forms.ListManagerBindingsCollection.AddCore(Binding dataBinding)
   at System.Windows.Forms.BindingsCollection.Add(Binding binding)
   at System.Windows.Forms.BindingContext.UpdateBinding(BindingContext newBindingContext, Binding binding)
   at System.Windows.Forms.Control.UpdateBindings()
   at System.Windows.Forms.Control.OnBindingContextChanged(EventArgs e)
   at System.Windows.Forms.ListControl.OnBindingContextChanged(EventArgs e)
   at System.Windows.Forms.Control.CreateControl()
   at System.Windows.Forms.Control.RecreateHandleCore()
   at System.Windows.Forms.ComboBox.RecreateHandleCore()
   at System.Windows.Forms.ComboBox.SetAutoComplete(Boolean reset, Boolean recreate)
   at System.Windows.Forms.ComboBox.ObjectCollection.ClearInternal()
   at System.Windows.Forms.ComboBox.OnDataSourceChanged(EventArgs e)
   at System.Windows.Forms.ListControl.SetDataConnection(Object newDataSource, BindingMemberInfo newDisplayMember, Boolean force)
   at System.Windows.Forms.ListControl.DataSourceDisposed(Object sender, EventArgs e)
   at System.ComponentModel.Component.Dispose(Boolean disposing)
   at System.Windows.Forms.BindingSource.Dispose(Boolean disposing)
   at System.ComponentModel.Component.Dispose()
   at System.ComponentModel.Container.Dispose(Boolean disposing)
   at System.ComponentModel.Container.Dispose()
   at MedAssociates.MedSales.ContactEditForm.Dispose(Boolean disposing) in C:\source\MedSales\MedSales\ContactEditForm.Designer.cs:line 14
   at System.ComponentModel.Component.Dispose()
   at System.Windows.Forms.Form.WmClose(Message& m)
   at System.Windows.Forms.Form.WndProc(Message& m)
   at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
   at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
   at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
Source: System.Windows.Forms

Any ideas?

Thanks
Andy

Brian Criswell replied on Monday, May 22, 2006

In CSLA 1.52 I inherited SWF.Form and SWF.UserControl and added this:

protected override void Dispose(bool disposing)
{
    if(disposing)
    {
        // Release managed resources
        Utilities.ClearBindings(this);
    }

    base.Dispose (disposing);
}

which calls this:


///
/// Clears all databindings from the control and all child controls.
///
/// The control from which to clear the databindings.
public static void ClearBindings(Control control)
{
    Binding[] bindings = new Binding[control.DataBindings.Count];
    control.DataBindings.CopyTo(bindings, 0);
    control.DataBindings.Clear();

    foreach(Binding binding in bindings)
        TypeDescriptor.Refresh(binding.DataSource);

    PropertyInfo dataSourceProperty = control.GetType().GetProperty("DataSource");
    if(dataSourceProperty != null)
        dataSourceProperty.SetValue(control, null, new object[] {});

    foreach(Control child in control.Controls)
        ClearBindings(child);
}

You may want to do something similar (basically clearing all databinding on Dispose()).

ajj3085 replied on Tuesday, May 23, 2006

Hey,

That seems to have worked.

I added this to the Dispose override:

// .Net 2.0
CountryComboBox.DataBindings.Clear();
StateComboBox.DataBindings.Clear();

Thanks for the tip; this is an odd error though.  It only seems to affects the ComboBoxes bound to the NameValueLists AND the Text property is databound.

Anyway, thanks for the tip!

Andy

Copyright (c) Marimer LLC