1

I have a Windows Forms application, and one of the forms has a couple of ComboBoxes that are both bound to the same BindingList of objects I have mapped via Entity Framework.

The Form_Load event calls this:

private void SetFacilityDropdowns()
{
    dbContext.Facilities.Load();
    var bindingSource = dbContext.Facilities.Local.ToBindingList();
    Dictionary<ComboBox, string> selectedDropDownsAndBoundFields = new Dictionary<ComboBox, string>
        {
            {FacilityId,    DataConstants.Facility.FacilityId},
            {FacilityName,  DataConstants.Facility.FacilityName}
        };
    SetDropdowns(bindingSource, selectedDropDownsAndBoundFields);            
}

The SetDropdowns method looks like this:

private static void SetDropdowns<T>(BindingList<T> dataSource, Dictionary<ComboBox, string> dropdownsAndBoundFields)
{
    if (dropdownsAndBoundFields == null)
    {
        return;
    }

    foreach (var dropdown in dropdownsAndBoundFields)
    {
        dropdown.Key.DataSource = dataSource;
        dropdown.Key.DisplayMember = dropdown.Value;
        dropdown.Key.ValueMember = dropdown.Value;
        dropdown.Key.AutoCompleteSource = AutoCompleteSource.ListItems;
        dropdown.Key.AutoCompleteMode = AutoCompleteMode.SuggestAppend;
        dropdown.Key.SelectedIndexChanged += Dropdown_SelectedIndexChanged;
    }
}

Everything looks fine, and both ComboBoxes appear to contain all of the items that I would expect them to. However, there are a few Facility objects from the Facilities table where the FacilityName property is null. This appears in the ComboBox as an empty string, although I don't know if it is only displayed that way or if it gets converted when it is bound.

Normally, when I change the FacilityName dropdown, the FacilityId dropdown changes to its matching value. However, when I change FacilityName to one of the null/empty string values, I get a NullReferenceException thrown. It appears to be thrown by the Windows Forms UI thread, so I can't set a breakpoint in any of the ComboBox "changed" events, because the exception gets thrown before any of the events get fired.

Any idea why this is happening?

EDIT:

Here is a stack trace:

>   NITS.exe!NITS.Program.CurrentDomain_UIThreadException(object sender, System.Threading.ThreadExceptionEventArgs t) Line 50   C#
    System.Windows.Forms.dll!System.Windows.Forms.Application.ThreadContext.OnThreadException(System.Exception t) + 0x8e bytes  
    System.Windows.Forms.dll!System.Windows.Forms.Control.WndProcException(System.Exception e) + 0x16 bytes 
    System.Windows.Forms.dll!System.Windows.Forms.Control.ControlNativeWindow.OnThreadException(System.Exception e) + 0xa bytes 
    System.Windows.Forms.dll!System.Windows.Forms.NativeWindow.Callback(System.IntPtr hWnd, int msg, System.IntPtr wparam, System.IntPtr lparam) + 0x9b bytes   
    [Native to Managed Transition]  
    [Managed to Native Transition]  
    System.Windows.Forms.dll!System.Windows.Forms.Control.SendMessage(int msg, System.IntPtr wparam, System.IntPtr lparam) + 0x21 bytes 
    System.Windows.Forms.dll!System.Windows.Forms.Control.ReflectMessageInternal(System.IntPtr hWnd, ref System.Windows.Forms.Message m) + 0x3b bytes   
    System.Windows.Forms.dll!System.Windows.Forms.Control.WmCommand(ref System.Windows.Forms.Message m) + 0x1b bytes    
    System.Windows.Forms.dll!System.Windows.Forms.Control.WndProc(ref System.Windows.Forms.Message m) + 0x3b7 bytes 
    System.Windows.Forms.dll!System.Windows.Forms.ScrollableControl.WndProc(ref System.Windows.Forms.Message m) + 0x2a bytes    
    System.Windows.Forms.dll!System.Windows.Forms.Form.WndProc(ref System.Windows.Forms.Message m) + 0x5e bytes 
    System.Windows.Forms.dll!System.Windows.Forms.Control.ControlNativeWindow.OnMessage(ref System.Windows.Forms.Message m) + 0x11 bytes    
    System.Windows.Forms.dll!System.Windows.Forms.Control.ControlNativeWindow.WndProc(ref System.Windows.Forms.Message m) + 0x35 bytes  
    System.Windows.Forms.dll!System.Windows.Forms.NativeWindow.Callback(System.IntPtr hWnd, int msg, System.IntPtr wparam, System.IntPtr lparam) + 0x80 bytes   
    [Native to Managed Transition]  
    [Managed to Native Transition]  
    System.Windows.Forms.dll!System.Windows.Forms.NativeWindow.DefWndProc(ref System.Windows.Forms.Message m) + 0x56 bytes  
    System.Windows.Forms.dll!System.Windows.Forms.Control.DefWndProc(ref System.Windows.Forms.Message m) + 0xa bytes    
    System.Windows.Forms.dll!System.Windows.Forms.Control.WmMouseDown(ref System.Windows.Forms.Message m, System.Windows.Forms.MouseButtons button, int clicks) + 0x3a bytes    
    System.Windows.Forms.dll!System.Windows.Forms.Control.WndProc(ref System.Windows.Forms.Message m) + 0x8da bytes 
    System.Windows.Forms.dll!System.Windows.Forms.ComboBox.WndProc(ref System.Windows.Forms.Message m) + 0x864 bytes    
    System.Windows.Forms.dll!System.Windows.Forms.Control.ControlNativeWindow.OnMessage(ref System.Windows.Forms.Message m) + 0x11 bytes    
    System.Windows.Forms.dll!System.Windows.Forms.Control.ControlNativeWindow.WndProc(ref System.Windows.Forms.Message m) + 0x35 bytes  
    System.Windows.Forms.dll!System.Windows.Forms.NativeWindow.Callback(System.IntPtr hWnd, int msg, System.IntPtr wparam, System.IntPtr lparam) + 0x80 bytes   
    [Native to Managed Transition]  
    [Managed to Native Transition]  
    System.Windows.Forms.dll!System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(System.IntPtr dwComponentID, int reason, int pvLoopData) + 0x24d bytes    
    System.Windows.Forms.dll!System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(int reason, System.Windows.Forms.ApplicationContext context) + 0x155 bytes  
    System.Windows.Forms.dll!System.Windows.Forms.Application.ThreadContext.RunMessageLoop(int reason, System.Windows.Forms.ApplicationContext context) + 0x4a bytes    
    System.Windows.Forms.dll!System.Windows.Forms.Application.Run(System.Windows.Forms.Form mainForm) + 0x31 bytes  
    NITS.exe!NITS.Program.Main() Line 37 + 0x1d bytes   C#
    [Native to Managed Transition]  
    [Managed to Native Transition]  
    mscorlib.dll!System.AppDomain.ExecuteAssembly(string assemblyFile, System.Security.Policy.Evidence assemblySecurity, string[] args) + 0x6b bytes    
    Microsoft.VisualStudio.HostingProcess.Utilities.dll!Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly() + 0x27 bytes  
    mscorlib.dll!System.Threading.ThreadHelper.ThreadStart_Context(object state) + 0x6f bytes   
    mscorlib.dll!System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool preserveSyncCtx) + 0xa7 bytes  
    mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool preserveSyncCtx) + 0x16 bytes  
    mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state) + 0x41 bytes    
    mscorlib.dll!System.Threading.ThreadHelper.ThreadStart() + 0x44 bytes   
    [Native to Managed Transition]  

The exception being thrown looks like this:

System.NullReferenceException Object reference not set to an instance of an object. System.String get_Text()    at System.Windows.Forms.ComboBox.get_Text()
   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.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
Douglas Barbin
  • 3,595
  • 2
  • 14
  • 34

2 Answers2

1

Your main exception is obviously

System.NullReferenceException Object reference not set to an instance of an object. System.String get_Text() at System.Windows.Forms.ComboBox.get_Text()

which leads me to believe that your combobox is trying to set the DisplayMember property to a null value. Since you said yourself you're not sure if the empty columns coming back from your database are represented as empty strings or null in the Facility class, you can explicity convert them in your getters. In addition, if you are passing in a Nullable to your FacilityID property, you need to convert it to an int so the combobox can handle it.

So, in your Facility class.

    public class Facility
    {
        private string _facilityName;
        private int _facilityID;

        public string FacilityName
        {
            get
            {
                if (_facilityName == null)
                    return String.Empty;
                else
                    return _facilityName;
            }
            set { _facilityName = value; }
        }

        public int FacilityID
        {
            get { return _facilityID; }
            set { _facilityID = value == null ? default(int) : value};
        }
    }

Using this, you'll make sure that you never have your control attempting to bind to a null value, and it should rid you of the exception.

Daniel Simpkins
  • 674
  • 5
  • 18
  • `Facility` is a class that is auto-generated by Entity Framework. – Douglas Barbin May 02 '14 at 15:32
  • Can you change the behavior of this class to make sure no null values are returned? – Daniel Simpkins May 02 '14 at 15:46
  • I can, and this actually works. I am going to try a few things and then return with my results. – Douglas Barbin May 02 '14 at 18:10
  • Okay, that solves the exception problem, but introduces a new one. When I select one of the null values, the accompanying value in the other dropdown becomes `System.Data.Entity.DynamicProxies.Facility_F4B14BF33FD7C299E70286AAFB2DE3802F40B0A50A6BF0EFD80BD6C4385597B6` (or some other long hex string at the end) instead of the correct `FacilityId` value. – Douglas Barbin May 02 '14 at 18:21
  • I am going to mark this as the answer, since it removes the exception. – Douglas Barbin May 02 '14 at 18:53
  • Okay I've updated the answer. I believe that the error you're getting is from trying to convert a Nullable value into an int. C# can't cast that by default, so you should return `default(int)` in that case. Hope it helps. Good luck. – Daniel Simpkins May 02 '14 at 19:01
  • Last comment isn't useful at all. `FacilityId` is the table's primary key and can never be nullable. – Douglas Barbin May 02 '14 at 19:26
0

You can try maybe to use IntelliTrace to get more info?

some_name
  • 1,183
  • 8
  • 13