all groups > dotnet windows forms databinding > september 2006 >
You're in the

dotnet windows forms databinding

group:

bind then unbind


bind then unbind Grady Morgan
9/26/2006 3:18:34 PM
dotnet windows forms databinding:
I have a series of controls (textboxes, checkboxes, and dropdowns)
which I am binding to a list of variables. Each control is assigned at
design time to a specific variable (by key). When that control's
variable does not exist in the variable list, I remove the control's
bindings and hide the control. Then, when the variable that the
control represents is added back to the list, I re-add all of the
bindings, and show the control. The second time the bindings are
added, I get an ArgumentException with the message: "Cannot bind to the
property or column Name on the DataSource.\n Parameter name:
dataMember."

I've created a small test app which duplicates the problem:

<code>
//class1 && class 2
public class Class1
{
private bool m_checked;

public bool Checked
{
get { return m_checked; }
set { m_checked = value; }
}

private Class2 m_class2;

public Class2 Class2
{
get { return m_class2; }
set { m_class2 = value; }
}
}

public class Class2
{
private string m_name;

public string Name
{
get { return m_name; }
set { m_name = value; }
}
}

//excerpt from form1.cs, form1 initializes all of the members
of data1 and data2
BindingSource source = new BindingSource();
Class1 data1;
Class2 data2;

private void Step1( object sender, EventArgs e )
{
source.DataSource = data1;

checkBox1.DataBindings.Add("Text", source, "Class2.Name");
checkBox1.DataBindings.Add("Checked", source, "Checked");
}

private void Step2( object sender, EventArgs e )
{
checkBox1.DataBindings.Clear();

source.DataSource = null;
}

private void Step3( object sender, EventArgs e )
{
source.DataSource = data2;

checkBox1.DataBindings.Add("Text", source, "Class2.Name");
checkBox1.DataBindings.Add("Checked", source, "Checked");
}
</code>

Step1 works fine, the control is bound to data1 and UI changes are
reflected in the object. Step2 disconects the CheckBox from data1, and
changes are no longer reflected.
Step3 (or Step1) causes the above argument exception to be thrown.

I'm guessing this is the improper way of handling intermitent binding,
but I can't find anything about another way to do it.

Thanks,
Grady Morgan
Re: bind then unbind Bart Mermuys
9/27/2006 12:00:00 AM
Hi,

[quoted text, click to view]

It looks more like a bug to me. First you setup a BindingSource with a
single object as the DataSource, the BindingSource will create a
BindingList<Class1> and put that single object into it (data1).

Then you bind to a subproperty (Class2.Name). What happens is that
DataBinding will create a related BindingSource which has a DataMember set
to Class2. This BindingSource creates a BindingList<Class2> containing the
single subobject (data1.Class2).

// created by you, manages bindings for "data1" properties
source.DataSource = data1
source.InnerList = BindingList<Class1> { data1 }

// implicitly created, manages bindings for "data1.Class2" properties
subSource.DataSource = source
subSource.DataMember = "Class2" // property
subSource.InnerList = BindingList<Class2> { data1.Class2 }

Everything still ok so far.

The master BindingSource (source) however caches all related BindingSource's
(eg. subSource). When the following is executed:
source.DataSource = null;

the master BindingSource (source) has no (list)properties anymore and the
related BindingSource (subSource) clears its DataMember because it's invalid
now:
subSource.DataMember = "";

Once you then set a new DataSource:
source.DataSource = data2;

the related BindingSource (subSource) still exists because it's cached and
it will be used again but it has *no DataMember anymore*, so (re)binding to
a property of a subobject which had a property bound before null will fail.

So at first sight this looks like a BindingSource bug: it doesn't remove
the cached/related BindingSource's when the DataSource is set to null.

Workarounds (not sure if you can use any considering your code was to
illustrate the problem):
- Don't set BindingSource.DataSource to null,
- drop the BindingSource and use a new one when you rebind or
- instead of setting BindingSource.DataSource to null, set it to
typeof(Class1), this way the master BindingSource doesn't loose its
(list)properties and the cached/related BindingSource's keep their
DataMember.eg.:

source.DataSource = typeof(Class1); // instead of null


HTH,
Greetings






[quoted text, click to view]

Re: bind then unbind Grady Morgan
10/10/2006 2:51:54 PM
Thanks, Bart, setting the datasource to the typeof(Class1) worked
great.

I'm wondering, how did you get this in depth knowledge about data
bindings. Do you have some way to debug through this stuff, or a
really good book I haven't seen.

Thanks,
Grady

[quoted text, click to view]
Re: bind then unbind Bart Mermuys
10/11/2006 1:13:24 PM
Hi,

[quoted text, click to view]

No books, just learning step by step. The first step would be to understand
the relations between CurrencyManager, BindingSource, Binding and
PropertyDescriptor.

You can also use Lutz Roeder reflector tool to look at the source code:
http://www.aisto.com/roeder/dotnet/

Greetings

[quoted text, click to view]

AddThis Social Bookmark Button