问题
I have a Windows Forms application, and one of the forms has a couple of ComboBox
es 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 ComboBox
es 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)
回答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.
回答2:
You can try maybe to use IntelliTrace to get more info?
来源:https://stackoverflow.com/questions/23273064/two-way-binding-with-windows-forms-combobox-throws-nullreferenceexception-when-c