Binding TextBox to Nested/Complex property - and what happens if theChild object is null?

E

EfyT

Hi all,

If I am binding a textbox to an object which has child object which
has a grand child object, and I want to bind to the property of the
grand child object, I want to show on the form / UserControl the
nested property i.e "Child.GrandChild.Description" is the datamember,
I get on error when disposing the form.

"Value cannot be null.\r\nParameter name: component"

To fix this, We can set the dataSource of the bindingSource to null
before the form is disposed, but the problem is that in my project
which is to big to bring up, I get the same error when a UserControl
finishes to load not only when it's disposed, but I just mannage to
reproduce the error when the form disposes and Ican't realize why.
So I think that if I find a proper workaround for this, I will be able
to fix my error too.

Any Ideas??

The following is the code to reproduce the Error, all you need is a
binding source that the DataSource will be set to typeof(Parent)
before you set the data member:
this.textBox1.DataBindings.Add("Text", this.class1BindingSource,
"Child.GrandChild.Description", true);

namespace NullDataBindingTest
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}

private void Form1_Load(object sender, EventArgs e)
{
//this.descriptionTextBox.DataBindings.Add("Text",
this.class1BindingSource, "Child.DescObject.Description",
true,DataSourceUpdateMode.OnPropertyChanged,"NONE");
this.textBox1.DataBindings.Add("Text",
this.class1BindingSource, "Child.GrandChild.Description", true,
DataSourceUpdateMode.OnPropertyChanged, "NONE");
Parent c1 = new Parent();
c1.Child = new Child();
//c1.Child.GrandChild = new GrandChild();
this.class1BindingSource.DataSource = c1;
}
}

public class Parent
{
private string _name;

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

private Child _child;

public Child Child
{
get { return _child; }
set { _child = value; }
}

}

public class Child
{
private string _name;

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

private GrandChild _grandChild;

public GrandChild GrandChild
{
get { return _grandChild; }
set { _grandChild = value; }
}


}

public class GrandChild
{
private string _description;

public string Description
{
get { return _description; }
set { _description = value; }
}

public override string ToString()
{
return Description;
}
}


}


StackTrace: at
System.ComponentModel.ReflectPropertyDescriptor.RemoveValueChanged
(Object component, EventHandler handler)
at System.Windows.Forms.BindToObject.CheckBinding()
at System.Windows.Forms.Binding.CheckBinding()
at System.Windows.Forms.Binding.SetBindableComponent
(IBindableComponent value)
at System.Windows.Forms.ControlBindingsCollection.ClearCore()
at System.Windows.Forms.BindingsCollection.Clear()
at System.Windows.Forms.ControlBindingsCollection.Clear()
at System.Windows.Forms.Control.ResetBindings()
at System.Windows.Forms.Control.Dispose(Boolean disposing)
at System.Windows.Forms.TextBox.Dispose(Boolean disposing)
at System.ComponentModel.Component.Dispose()
at System.Windows.Forms.Control.Dispose(Boolean disposing)
at System.Windows.Forms.ContainerControl.Dispose(Boolean disposing)
at System.Windows.Forms.Form.Dispose(Boolean disposing)
at NullDataBindingTest.Form1.Dispose(Boolean disposing) in C:\Users
\Public\!SVN\SandBox\NullDataBindingTest\NullDataBindingTest
\Form1.Designer.cs:line 20
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.DebuggableCallback(IntPtr
hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
at System.Windows.Forms.UnsafeNativeMethods.CallWindowProc(IntPtr
wndProc, IntPtr hWnd, Int32 msg, IntPtr wParam, IntPtr lParam)
at System.Windows.Forms.NativeWindow.DefWndProc(Message& m)
at System.Windows.Forms.Form.DefWndProc(Message& m)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.ScrollableControl.WndProc(Message& m)
at System.Windows.Forms.ContainerControl.WndProc(Message& m)
at System.Windows.Forms.Form.WmSysCommand(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.DebuggableCallback(IntPtr
hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
at System.Windows.Forms.UnsafeNativeMethods.CallWindowProc(IntPtr
wndProc, IntPtr hWnd, Int32 msg, IntPtr wParam, IntPtr lParam)
at System.Windows.Forms.NativeWindow.DefWndProc(Message& m)
at System.Windows.Forms.Form.DefWndProc(Message& m)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.ScrollableControl.WndProc(Message& m)
at System.Windows.Forms.ContainerControl.WndProc(Message& m)
at System.Windows.Forms.Form.WmNcButtonDown(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.DebuggableCallback(IntPtr
hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG&
msg)
at
System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop
(Int32 dwComponentID, Int32 reason, Int32 pvLoopData)
at
System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner
(Int32 reason, ApplicationContext context)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoop
(Int32 reason, ApplicationContext context)
at System.Windows.Forms.Application.Run(Form mainForm)
at NullDataBindingTest.Program.Main() in C:\Users\Public\!SVN
\SandBox\NullDataBindingTest\NullDataBindingTest\Program.cs:line 18
at System.AppDomain._nExecuteAssembly(Assembly assembly, String[]
args)
at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence
assemblySecurity, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly
()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.Run(ExecutionContext
executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()
 
M

Morten Wennevik [C# MVP]

Hi,

The problem is you are binding to properties that are NULL.

When a Control is disposed Control.ResetBindings() is called. During this
process the DataBinding tries to tidy up and among other things tries to
remove a PropertyChanged subscription, and the error message comes from some
reflection code being done on GrandChild.

There is actually code that is not run if you set up the BindingSource to
databind against a type. If you instead databound directly against an
instance of Parent you would have seen this error immediatly when you
databound against GrandChild.

I assume you already discovered this as you have commented out
c1.Child.GrandChild = new GrandChild(), which would solve the problem.

Parent c1 = new Parent();
c1.Child = new Child();
//c1.Child.GrandChild = new GrandChild();

BindingSource class1BindingSource = new BindingSource(c1, "");

// This blows up if GrandChild is null
this.textBox1.DataBindings.Add("Text",
class1BindingSource,
"Child.GrandChild.Description",
true,
DataSourceUpdateMode.OnPropertyChanged,
"NONE");


--
Happy Coding!
Morten Wennevik [C# MVP]


EfyT said:
Hi all,

If I am binding a textbox to an object which has child object which
has a grand child object, and I want to bind to the property of the
grand child object, I want to show on the form / UserControl the
nested property i.e "Child.GrandChild.Description" is the datamember,
I get on error when disposing the form.

"Value cannot be null.\r\nParameter name: component"

To fix this, We can set the dataSource of the bindingSource to null
before the form is disposed, but the problem is that in my project
which is to big to bring up, I get the same error when a UserControl
finishes to load not only when it's disposed, but I just mannage to
reproduce the error when the form disposes and Ican't realize why.
So I think that if I find a proper workaround for this, I will be able
to fix my error too.

Any Ideas??

The following is the code to reproduce the Error, all you need is a
binding source that the DataSource will be set to typeof(Parent)
before you set the data member:
this.textBox1.DataBindings.Add("Text", this.class1BindingSource,
"Child.GrandChild.Description", true);

namespace NullDataBindingTest
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}

private void Form1_Load(object sender, EventArgs e)
{
//this.descriptionTextBox.DataBindings.Add("Text",
this.class1BindingSource, "Child.DescObject.Description",
true,DataSourceUpdateMode.OnPropertyChanged,"NONE");
this.textBox1.DataBindings.Add("Text",
this.class1BindingSource, "Child.GrandChild.Description", true,
DataSourceUpdateMode.OnPropertyChanged, "NONE");
Parent c1 = new Parent();
c1.Child = new Child();
//c1.Child.GrandChild = new GrandChild();
this.class1BindingSource.DataSource = c1;
}
}

public class Parent
{
private string _name;

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

private Child _child;

public Child Child
{
get { return _child; }
set { _child = value; }
}

}

public class Child
{
private string _name;

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

private GrandChild _grandChild;

public GrandChild GrandChild
{
get { return _grandChild; }
set { _grandChild = value; }
}


}

public class GrandChild
{
private string _description;

public string Description
{
get { return _description; }
set { _description = value; }
}

public override string ToString()
{
return Description;
}
}


}


StackTrace: at
System.ComponentModel.ReflectPropertyDescriptor.RemoveValueChanged
(Object component, EventHandler handler)
at System.Windows.Forms.BindToObject.CheckBinding()
at System.Windows.Forms.Binding.CheckBinding()
at System.Windows.Forms.Binding.SetBindableComponent
(IBindableComponent value)
at System.Windows.Forms.ControlBindingsCollection.ClearCore()
at System.Windows.Forms.BindingsCollection.Clear()
at System.Windows.Forms.ControlBindingsCollection.Clear()
at System.Windows.Forms.Control.ResetBindings()
at System.Windows.Forms.Control.Dispose(Boolean disposing)
at System.Windows.Forms.TextBox.Dispose(Boolean disposing)
at System.ComponentModel.Component.Dispose()
at System.Windows.Forms.Control.Dispose(Boolean disposing)
at System.Windows.Forms.ContainerControl.Dispose(Boolean disposing)
at System.Windows.Forms.Form.Dispose(Boolean disposing)
at NullDataBindingTest.Form1.Dispose(Boolean disposing) in C:\Users
\Public\!SVN\SandBox\NullDataBindingTest\NullDataBindingTest
\Form1.Designer.cs:line 20
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.DebuggableCallback(IntPtr
hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
at System.Windows.Forms.UnsafeNativeMethods.CallWindowProc(IntPtr
wndProc, IntPtr hWnd, Int32 msg, IntPtr wParam, IntPtr lParam)
at System.Windows.Forms.NativeWindow.DefWndProc(Message& m)
at System.Windows.Forms.Form.DefWndProc(Message& m)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.ScrollableControl.WndProc(Message& m)
at System.Windows.Forms.ContainerControl.WndProc(Message& m)
at System.Windows.Forms.Form.WmSysCommand(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.DebuggableCallback(IntPtr
hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
at System.Windows.Forms.UnsafeNativeMethods.CallWindowProc(IntPtr
wndProc, IntPtr hWnd, Int32 msg, IntPtr wParam, IntPtr lParam)
at System.Windows.Forms.NativeWindow.DefWndProc(Message& m)
at System.Windows.Forms.Form.DefWndProc(Message& m)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.ScrollableControl.WndProc(Message& m)
at System.Windows.Forms.ContainerControl.WndProc(Message& m)
at System.Windows.Forms.Form.WmNcButtonDown(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.DebuggableCallback(IntPtr
hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG&
msg)
at
System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop
(Int32 dwComponentID, Int32 reason, Int32 pvLoopData)
at
System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner
(Int32 reason, ApplicationContext context)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoop
(Int32 reason, ApplicationContext context)
at System.Windows.Forms.Application.Run(Form mainForm)
at NullDataBindingTest.Program.Main() in C:\Users\Public\!SVN
\SandBox\NullDataBindingTest\NullDataBindingTest\Program.cs:line 18
at System.AppDomain._nExecuteAssembly(Assembly assembly, String[]
args)
at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence
assemblySecurity, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly
()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.Run(ExecutionContext
executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top