3
votes

I have .Net 2.0 Windows form containing combobxes. I have written following code to populate combobox and then binding it to ProductType property of type Int.

// Populate Combo

cmbProduct.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
cmbProduct.DataSource = new DataView(productDataSet.Tables[0]);
cmbProduct.DisplayMember = displayColumnName_;
cmbProduct.ValueMember = idColumnaName_;

// Add Databindings

cmbProduct.DataBindings.Add("SelectedValue", this, "ProductType").DataSourceUpdateMode = DataSourceUpdateMode.OnPropertyChanged;

ISSUE

  1. Run application.
  2. Click on ComboBox's drop-down arrow but do not select any item.
  3. Press any keys (such as ALT+TAB, Windows Key etc) which will shift focus from current Windows form application.

This throws Exception and application crashes. Following are the details taken from Output window.

A first chance exception of type 'System.ArgumentException' occurred in System.Windows.Forms.dll Object of type 'System.DBNull' cannot be converted to type 'System.Int32'. at System.ComponentModel.ReflectPropertyDescriptor.SetValue(Object component, Object value) at System.Windows.Forms.BindToObject.SetValue(Object value) at System.Windows.Forms.Binding.PullData(Boolean reformat, Boolean force) at System.Windows.Forms.Binding.Target_PropertyChanged(Object sender, EventArgs e) at System.EventHandler.Invoke(Object sender, EventArgs e) at System.Windows.Forms.ListControl.OnSelectedValueChanged(EventArgs e) at System.Windows.Forms.ComboBox.OnSelectedValueChanged(EventArgs e) at System.Windows.Forms.ComboBox.OnSelectedIndexChanged(EventArgs e) at System.Windows.Forms.ComboBox.WmReflectCommand(Message& m) at System.Windows.Forms.ComboBox.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.SendMessage(HandleRef hWnd, Int32 msg, IntPtr wParam, IntPtr lParam) at System.Windows.Forms.Control.SendMessage(Int32 msg, IntPtr wparam, IntPtr lparam) at System.Windows.Forms.Control.ReflectMessageInternal(IntPtr hWnd, Message& m) at System.Windows.Forms.Control.WmCommand(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.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.Control.DefWndProc(Message& m) at System.Windows.Forms.Control.WmCommand(Message& m) at System.Windows.Forms.Control.WndProc(Message& m) at System.Windows.Forms.ComboBox.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.PeekMessage(MSG& msg, HandleRef hwnd, Int32 msgMin, Int32 msgMax, Int32 remove) 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)

I added some debug statment in event handlers to check the event sequence. The output window deatails are as shown below :

cmbProduct_SelectionChangeCommitted occured - SelectedValue is NULL
cmbProduct_SelectedValueChanged occured - New SelectedValue is NULL
The thread 0x1728 has exited with code 0 (0x0).
cmbProduct_SelectedIndexChanged occured - New SelectedIndex is -1
The thread 0x1250 has exited with code 0 (0x0).

Question

Why .Net fires SelectionChangeCommitted, SelectedValueChanged and SelectedIndexChanged events when the application loses its focus with combobox state is OPEN ?

2

2 Answers

2
votes

The code looks perfect. The issue maybe because of bug in .net framework. Can some expert confirm this ?

One workaround to avoid the exception is - store default value of "ProductType" property if SelectedValue is NULL.

For example, if default value of ProductType is -1 then,

cmbProduct.DataBindings["SelectedValue"].DataSourceNullValue = -1; 

Hope, this helps!

Robin

0
votes

It sounds like you are asking the wrong question: "Why does the combo commit on focus loss?" rather than "Why is the exception thrown?"

Robin correctly answered the important one.

The user doesn't need to perform the convoluted 3 steps you provided to see the exception - merely selecting the offending (null) index will cause it.