使用Windows窗体ComboBox进行双向绑定会在更改时抛出NullReferenceException

时间:2014-04-24 15:19:01

标签: c# winforms data-binding binding combobox

我有一个Windows窗体应用程序,其中一个窗体有两个ComboBox es,它们都绑定到我通过Entity Framework映射的相同BindingList个对象。

Form_Load事件称之为:

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);            
}

SetDropdowns方法如下所示:

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;
    }
}

一切看起来都不错,ComboBox似乎都包含了我期望它们的所有项目。但是,Facility表中有一些Facilities个对象,其中FacilityName属性为null。这在ComboBox中显示为空字符串,但我不知道它是仅以这种方式显示还是在绑定时被转换。

通常,当我更改FacilityName下拉列表时,FacilityId下拉列表会更改为其匹配值。但是,当我将FacilityName更改为其中一个空/空字符串值时,我会抛出NullReferenceException。它似乎是由Windows窗体UI线程抛出的,因此我无法在ComboBox&#34;更改&#34;中的任何一个中设置断点。事件,因为在任何事件被触发之前抛出异常。

知道为什么会这样吗?

编辑:

这是一个堆栈跟踪:

>   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]  

抛出的异常如下所示:

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)

2 个答案:

答案 0 :(得分:1)

您的主要例外显然是

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

这让我相信你的组合框试图将DisplayMember属性设置为空值。既然你自己说过你不确定从数据库返回的空列是否在Facility类中表示为空字符串或null,你可以明确地在getter中转换它们。此外,如果您将Nullable传递给FacilityID属性,则需要将其转换为int,以便组合框可以处理它。

所以,在你的Facility班。

    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};
        }
    }

使用它,你将确保你永远不会让你的控件试图绑定到空值,它应该摆脱你的异常。

答案 1 :(得分:0)

您可以尝试使用IntelliTrace获取更多信息吗?