Hi,
[quoted text, click to view] "Grady Morgan" <GradyMorgan@gmail.com> wrote in message
news:1159309114.676625.7940@h48g2000cwc.googlegroups.com...
>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.
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] >
> Thanks,
> Grady Morgan
>