Binding error: Invalid cast from 'DBNull' to 'Guid'
I'm currently experiencing some problems with the binding source component:
I've a procedure that sets the value of a uniqueidentifier (guid) column in a datarowview to DBNull. The datatable, from which the datarowview was created allows dbnull for this column.
The column is bound to a property named "selectedvalue" of a control that I've written (derived from user control). The property's type is "object".
The binding works fine until I enter my control and try to leave it. The validation event is fired and I receive the following bindingerror:
"Invalid cast from 'DBNull' to 'Guid'"
I tried to set "selectedvalue" to nothing before the binding starts ("onValidating" event of the usercontrol) but it doesn't seem to "update" the bindingvalue. I still receive the error message.
Could anybody give me some hints?
Thank you!
[862 byte] By [
TAS] at [2007-12-16]
How have you setup binding? It looks like you may be binding the typed DataRow rather than the DataRowView. If you're not binding to the typed DataRow - can you provide a sample?
Thanks,
Joe Stegman
The Windows Forms Team
Microsoft Corp.
This posting is provided "AS IS" with no warranties, and confers no rights.
Thank you for this tip, but I already checked it. I don't bind to a DataRow. Unfortunatly my binding methods are hard to extract to a small test project because they are embedded in my project and have lot of references to other project parts. But I try to explain how I do some bindings:
I created some user controls that act like endless forms (like in Access). I have different panel controls and one panel container. This contains controls the panels, do the bindings, etc.
Each panel and the container has a bindingsource, a dataset and a binding method that is called after initialization. The controls in each panel are bound to the bindingsource.
After showing the form, the BindingSource.Datasource and BindingSource.DataMember properties of the container are set to DataTable in a DataTable that was loaded before. The binding method of the container iterates throw the BindingSource items and sets the BindingSource.DataSource property of each panel to Container.BindingSource.Item(i).
Everything works fine except the binding to the SelectedValue property of another user control. The SelectedValue property of a combobox also works...
Are thery any mistakes in my basic architecture? Or could it be a bug?
Thank you!
BTW: I recognized another strange behaviour of the BindingSource component:
If I sort the BindingSource by setting the "Sort"-Property, and change the values of the sorting fields in the datarow, the BindingSource binds to, sorting doesn't work anymore. The values in the BindingSource Items have to correct content but the list is not sorted correctly. I also tried to "RemoveSort" and set "Sort" new - without success...?
TAS at 2007-9-9 >

The architecture seems reasonable. Can you post a stack trace - this may help in determining the cause?
As for the second issue, did you call EndEdit() after making your change? Another option would be to call BindingSource.ResetBindings(false) - but you shouldn't have to do this (the underlying DataView should fire an event that will cause the BindingSource/Controls to refresh).
Joe Stegman
The Windows Forms Team
Microsoft Corp.
This posting is provided "AS IS" with no warranties, and confers no rights.
I've had problems in the past with binding ComboBoxes to a property. You probably don't want to create just a little DataTable for databinding that Combo to, but it might solve your problem. Doesn't hurt to give it a try.
I added the EndEdit() method and now it works. But I've a general question about this method: Do I have to call this method whenever I change values in a DataTable by DataTable.Rows(i).Item("Test") = "xy"? I only experienced this sorting problems and the rest of my program works without EndEdit...?
Here comes the call stack of the BindingComplete event of the panel's BindingSource. It was shot during the binding error. I hope it will help.
Thank you!
--
MeBestFE.EXE!MeBestFE.Controls.Basis.BCtrl_MeBestBoundControl.MainBindingSource_BindingComplete(Object sender = {MeBestFE.Controls.Basis.BCtrl_BindingSource}, System.Windows.Forms.BindingCompleteEventArgs e = {System.Windows.Forms.BindingCompleteEventArgs}) Line 101 Basic
System.Windows.Forms.dll!System.Windows.Forms.BindingSource.OnBindingComplete(System.Windows.Forms.BindingCompleteEventArgs e) + 0x67 bytes
System.Windows.Forms.dll!System.Windows.Forms.BindingSource.CurrencyManager_BindingComplete(object sender, System.Windows.Forms.BindingCompleteEventArgs e) + 0x9 bytes
System.Windows.Forms.dll!System.Windows.Forms.BindingManagerBase.OnBindingComplete(System.Windows.Forms.BindingCompleteEventArgs args) + 0x16 bytes
System.Windows.Forms.dll!System.Windows.Forms.BindingManagerBase.Binding_BindingComplete(object sender, System.Windows.Forms.BindingCompleteEventArgs args) + 0x9 bytes
System.Windows.Forms.dll!System.Windows.Forms.Binding.OnBindingComplete(System.Windows.Forms.BindingCompleteEventArgs e = {System.Windows.Forms.BindingCompleteEventArgs}) + 0x27 bytes
System.Windows.Forms.dll!System.Windows.Forms.Binding.PullData(bool reformat, bool force) + 0x1ff bytes
System.Windows.Forms.dll!System.Windows.Forms.Binding.Target_Validate(object sender, System.ComponentModel.CancelEventArgs e) + 0x1a bytes
[Native to Managed Transition]
[Managed to Native Transition]
System.Windows.Forms.dll!System.Windows.Forms.Control.OnValidating(System.ComponentModel.CancelEventArgs e) + 0x62 bytes
MeBestFE.EXE!MeBestFE.Controls.Ctrl_ComboBoxExtended.Ctrl_ComboboxExtended.OnValidating(System.ComponentModel.CancelEventArgs e = {System.ComponentModel.CancelEventArgs}) Line 163 + 0xa bytes Basic
System.Windows.Forms.dll!System.Windows.Forms.Control.PerformControlValidation(bool bulkValidation = false) + 0x3e bytes
System.Windows.Forms.dll!System.Windows.Forms.ContainerControl.ValidateThroughAncestor(System.Windows.Forms.Control ancestorControl = {System.Windows.Forms.GroupBox, Text: Von}, bool preventFocusChangeOnError = true) + 0x107 bytes
System.Windows.Forms.dll!System.Windows.Forms.ContainerControl.EnterValidation(System.Windows.Forms.Control enterControl) + 0x78 bytes
System.Windows.Forms.dll!System.Windows.Forms.ContainerControl.UpdateFocusedControl() + 0x7c bytes
System.Windows.Forms.dll!System.Windows.Forms.ContainerControl.AssignActiveControlInternal(System.Windows.Forms.Control value = {MeBestFE.Controls.Ctrl_ComboBoxExtended.Ctrl_ComboboxExtendedAnschriften}) + 0x20 bytes
System.Windows.Forms.dll!System.Windows.Forms.ContainerControl.ActivateControlInternal(System.Windows.Forms.Control control, bool originator) + 0x4a bytes
"System.Windows.Forms.dll!System.Windows.Forms.ContainerControl.ActivateControlInternal(System.Windows.Forms.Control control = {Text = """"}, bool originator = true) + 0xb1 bytes"
System.Windows.Forms.dll!System.Windows.Forms.ContainerControl.ActivateControlInternal(System.Windows.Forms.Control control) + 0x7 bytes
System.Windows.Forms.dll!System.Windows.Forms.Control.WmSetFocus(ref System.Windows.Forms.Message m = {msg=0x7 (WM_SETFOCUS) hwnd=0x3c074c wparam=0x2f078c lparam=0x0 result=0x0}) + 0x67 bytes
System.Windows.Forms.dll!System.Windows.Forms.Control.WndProc(ref System.Windows.Forms.Message m) + 0x757 bytes
System.Windows.Forms.dll!System.Windows.Forms.TextBoxBase.WndProc(ref System.Windows.Forms.Message m) + 0x8e bytes
System.Windows.Forms.dll!System.Windows.Forms.TextBox.WndProc(ref System.Windows.Forms.Message m) + 0x7d bytes
System.Windows.Forms.dll!System.Windows.Forms.Control.ControlNativeWindow.OnMessage(ref System.Windows.Forms.Message m) + 0xb bytes
System.Windows.Forms.dll!System.Windows.Forms.Control.ControlNativeWindow.WndProc(ref System.Windows.Forms.Message m) + 0xd6 bytes
System.Windows.Forms.dll!System.Windows.Forms.NativeWindow.DebuggableCallback(System.IntPtr hWnd, int msg, System.IntPtr wparam, System.IntPtr lparam) + 0x40 bytes
[Native to Managed Transition]
[Managed to Native Transition]
System.Windows.Forms.dll!System.Windows.Forms.Control.FocusInternal() + 0x3c bytes
System.Windows.Forms.dll!System.Windows.Forms.TextBox.WndProc(ref System.Windows.Forms.Message m = {msg=0x201 (WM_LBUTTONDOWN) hwnd=0x3c074c wparam=0x1 lparam=0xc0038 result=0x0}) + 0x3a bytes
System.Windows.Forms.dll!System.Windows.Forms.Control.ControlNativeWindow.OnMessage(ref System.Windows.Forms.Message m) + 0xb bytes
System.Windows.Forms.dll!System.Windows.Forms.Control.ControlNativeWindow.WndProc(ref System.Windows.Forms.Message m) + 0xd6 bytes
System.Windows.Forms.dll!System.Windows.Forms.NativeWindow.DebuggableCallback(System.IntPtr hWnd, int msg, System.IntPtr wparam, System.IntPtr lparam) + 0x40 bytes
[Native to Managed Transition]
[Managed to Native Transition]
System.Windows.Forms.dll!System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(int dwComponentID, int reason, int pvLoopData) + 0x2e4 bytes
System.Windows.Forms.dll!System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(int reason = -1, System.Windows.Forms.ApplicationContext context = {System.Windows.Forms.ApplicationContext}) + 0x17a bytes
System.Windows.Forms.dll!System.Windows.Forms.Application.ThreadContext.RunMessageLoop(int reason, System.Windows.Forms.ApplicationContext context) + 0x53 bytes
System.Windows.Forms.dll!System.Windows.Forms.Application.Run(System.Windows.Forms.Form mainForm) + 0x2e bytes
MeBestFE.EXE!MeBestFE.Main.main() Line 37 + 0xb bytes Basic
[Native to Managed Transition]
[Managed to Native Transition]
mscorlib.dll!System.AppDomain.ExecuteAssembly(string assemblyFile, System.Security.Policy.Evidence assemblySecurity, string[] args) + 0x38 bytes
Microsoft.VisualStudio.HostingProcess.Utilities.dll!Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly() + 0x1d bytes
mscorlib.dll!System.Threading.ThreadHelper.ThreadStart_Context(object state) + 0x3b bytes
mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state) + 0x7d bytes
> mscorlib.dll!System.Threading.ThreadHelper.ThreadStart() + 0x40 bytes
TAS at 2007-9-9 >

>> But I've a general question about this method: Do I have to call this method whenever I change values in a DataTable by DataTable.Rows(i).Item("Test") = "xy"?
No - you only need to call this when going through a DataRowView. The DataRowView implements IEditableObject which provides row level commit semantics (begin edit, commit edit and rollback edit).
>> Here comes the call stack of the BindingComplete event of the panel's BindingSource. It was shot during the binding error.
The exception appears to be happening in your code - it appears you've hooked BindingComplete and the exception is the result of something you're doing in your BindingComplete handler. Can you post your BindingComplete handler?
Joe Stegman
The Windows Forms Team
Microsoft Corp.
This posting is provided "AS IS" with no warranties, and confers no rights.
You're right - the exception happens in my code. But just because I set a breakpoint on the WriteLine-codeline to get a call stack. | |
Private Sub MainBindingSource_BindingComplete(ByVal sender As System.Object, ByVal e As System.Windows.Forms.BindingCompleteEventArgs) Handles MainBindingSource.BindingComplete If e.BindingCompleteState = BindingCompleteState.Exception Then Debug.WriteLine(e.Binding.Control.Name + ": " & e.ErrorText) End If If TypeOf e.Exception Is FormatException Then MessageBox.Show("Bitte geben Sie einen gültigen Wert ein!", "Ungültige Eingabe", MessageBoxButtons.OK, MessageBoxIcon.Error) If TypeOf e.Exception Is ArgumentException Then MessageBox.Show("Der Wert, den Sie eingegeben haben, ist zu lange. Bitte geben Sie einen gültigen Wert ein!", "Ungültige Eingabe", MessageBoxButtons.OK, MessageBoxIcon.Error) End Sub |
I hooked on this event to catch the most common binding errors (input errors etc.) and present more specific error messages for the user. Is there anything wrong with it?Thank you a lot!
TAS at 2007-9-9 >

OK - can you provide the stack trace from the Exception:
| | If e.BindingCompleteState = BindingCompleteState.Exception Then Debug.WriteLine(e.Binding.Control.Name + ": " & e.Exception.StackTrace) End If |
Thanks,
Joe Stegman
The Windows Forms Team
Microsoft Corp.
This posting is provided "AS IS" with no warranties, and confers no rights.
Ok. Here is the stack trace from the exception:
at System.Windows.Forms.Formatter.ChangeType(Object value, Type type, IFormatProvider formatInfo)
at System.Windows.Forms.Formatter.ParseObjectInternal(Object value, Type targetType, Type sourceType, TypeConverter targetConverter, TypeConverter sourceConverter, IFormatProvider formatInfo, Object formattedNullValue)
at System.Windows.Forms.Formatter.ParseObject(Object value, Type targetType, Type sourceType, TypeConverter targetConverter, TypeConverter sourceConverter, IFormatProvider formatInfo, Object formattedNullValue, Object dataSourceNullValue)
at System.Windows.Forms.Binding.ParseObject(Object value)
at System.Windows.Forms.Binding.PullData(Boolean reformat, Boolean force)
Thanks a lot for your efforts!
TAS at 2007-9-9 >

Your Binding instance has a property on it called DataSourceNullValue - try setting this to DBNull.Value (binding.DataSourceNullValue = DBNull.Value).
Also, I'm not sure where the DBNull is coming from - do you set your UserControl property value to DBNull.Value?
Joe Stegman
The Windows Forms Team
Microsoft Corp.
This posting is provided "AS IS" with no warranties, and confers no rights.
I set the DataSourceNullValue to DBNull.Value - without success. It still throws the same exception.
Not the usercontrol property is set to DBNull.Value but the field in the datatable, the usercontrol is bound to:
I have a combobox that contains some user options. If the user selects one of the options (selectionChangeCommitted), some fields in the current datarow are set to DBNull.Value:
| | Row.Item("FieldA") = DBNull.Value Row.Item("FieldB") = DBNULL.Value |
FieldA is bound to a combobox and FieldB is bound to my user control. Both fields are cleared (but just after leaving the option combobox?) and I can enter and leave to FieldA-combobox without problems. But after entering FieldB-user control I cannot leave it anymore because it throws this exception.
I hope my description is understandable...
Thanks a lot!
TAS at 2007-9-9 >

<quote>I've a procedure that sets the value of a uniqueidentifier (guid) column in a datarowview to DBNull. The datatable, from which the datarowview was created allows dbnull for this column. </quote>
I think we are overlooking the obvious...a GUID is typically used as a primary key which can not be null in the DB even though your datatable will allow the null...
Also only the Object type can be set to DBNull.value...
MyInteger = DBNull.value 'throws exception
MyObject = DBNull.value 'OK
Well, I'm a little stumped as I'm unable to recreate this issue. Can you generate a sample the reproduces the issue and post it? Another option would be to generate a sample application and post it in the form of a bug here http://lab.msdn.microsoft.com/ProductFeedback/. Either way, I'll take a look.
Joe Stegman
The Windows Forms Team
Microsoft Corp.
This posting is provided "AS IS" with no warranties, and confers no rights.
It's unfortunately not that easy:
- the GUID/uniqueidentifier column I'm talking about is not a primary key and allows DBNull values (in the dataset and in the datatable).
- the datatype of the property of my user control is "object".
Besides that: both errors would throw other exceptions earlier during execution.
But anyway thank you for your proposals...
@Joe:
I will try to create such a sample but as I said before - it's very deep anchored in my application, so I don't know exactly how I can cut it out...
Regards.
TAS at 2007-9-9 >
