OnListChanged中的DataView NullReferenceException

时间:2009-11-13 16:04:47

标签: c# winforms nullreferenceexception dataview

我有一个相当复杂的WinForms应用程序,它使用数据绑定将强类型DataTable绑定到控件(不确定这个事实是否在这里很重要)。当对列的更改触发更新同一行上的另一列(或至少这是我的理论)的逻辑时,会引发异常。

示例:客户记录绑定到ComboBox,其中包含Customer :: MarketingContactId的联系人列表。当联系人更改时,会有多个文本框和复选框将更新,以允许编辑该联系人的详细信息。其中一个复选框在CheckChanged上有一个事件处理程序

void MarketingContactIsFulltimeChangedHandler(object sender, EventArgs e)
{
   var contact = m_row.MarketingContact;
   if (contact != null && contact.IsFullTimeEmployee)
   {
      var i = m_row.Institution;
      if (i.CreditLevel > m_row.CreditLevel)
         m_row.CreditLevel = i.CreditLevel;
   }
}

m_row是客户得到更新。但是,此代码中不会发生错误,但实际上是从MarketingContactId字段的设置中引发的。这是调用堆栈,它证实了这一点:

  

System.Data.dll中!System.Data.DataView.OnListChanged(System.ComponentModel.ListChangedEventArgs   e = {System.ComponentModel.ListChangedEventArgs})第1433行+ 0x2c   字节C#       System.Data.dll!System.Data.DataView.IndexListChanged(object sender,System.ComponentModel.ListChangedEventArgs e =   {System.ComponentModel.ListChangedEventArgs})第1299行C#   System.Data.dll中!System.Data.DataView.IndexListChangedInternal(System.ComponentModel.ListChangedEventArgs   e)1324行C#
  System.Data.dll中!System.Data.DataViewListener.IndexListChanged(System.ComponentModel.ListChangedEventArgs   e)76行+ 0x7字节C#
  System.Data.dll中!System.Data.Index.OnListChanged.AnonymousMethod(System.Data.DataViewListener   listener,System.ComponentModel.ListChangedEventArgs args,bool arg2,   bool arg3)803行+ 0x7字节C#
  System.Data.dll中!System.Data.Listeners.Notify(System.ComponentModel.ListChangedEventArgs   arg1 = {System.ComponentModel.ListChangedEventArgs},bool arg2 =   false,bool arg3 = false,   System.Data.Listeners.Action   action = {Method = {Void   b__2(System.Data.DataViewListener,   System.ComponentModel.ListChangedEventArgs,Boolean,Boolean)}})Line   1029 + 0x1a字节C#   System.Data.dll中!System.Data.Index.OnListChanged(System.ComponentModel.ListChangedEventArgs   e)805 C#线   System.Data.dll中!System.Data.Index.OnListChanged(System.ComponentModel.ListChangedType   changedType,int newIndex,int oldIndex)788行#C#   System.Data.dll!System.Data.Index.RecordStateChanged(int oldRecord,   System.Data.DataViewRowState oldOldState,System.Data.DataViewRowState   oldNewState,int newRecord,System.Data.DataViewRowState newOldState,   System.Data.DataViewRowState newNewState)行903 + 0x10字节C#
  System.Data.dll!System.Data.DataTable.RecordStateChanged(int record1 =   0,System.Data.DataViewRowState oldState1 =已添加,   System.Data.DataViewRowState newState1 = None,int record2 = 1,   System.Data.DataViewRowState oldState2 = None,   System.Data.DataViewRowState newState2 =已添加)行3473 + 0x18字节   C#   System.Data.dll中!System.Data.DataTable.SetNewRecordWorker(的System.Data.DataRow   row =“CustomerRow:Id:-1”,int proposedRecord,   System.Data.DataRowAction action = Change,bool isInMerge,int   position,bool fireEvent = true,out System.Exception   deferredException = null)行3935 + 0x16字节C#
  System.Data.dll中!System.Data.DataTable.SetNewRecord(的System.Data.DataRow   row,int proposedRecord,System.Data.DataRowAction action,bool   isInMerge,bool fireEvent)3824号线C#   System.Data.dll!System.Data.DataRow.SetNewRecord(int record)第1160行   C#System.Data.dll!System.Data.DataRow.EndEdit()第631行+ 0xa   字节C#
  System.Data.dll中!System.Data.DataRow.this [System.Data.DataColumn] .SET(System.Data.DataColumn   列,对象值)第343行C#

行号是因为我从Visual Studio的MS Symbol Server功能中为System.Data.dll加载了符号。拥有这些数据可以让我进一步跟踪OnListChanged方法的这部分错误:

// snippet from System.Data.DataView::OnListChanged(ListChangedEventArgs e)
if (onListChanged != null) { 
   if ((col != null) && (e.NewIndex == e.OldIndex)) {
      ListChangedEventArgs newEventArg = new ListChangedEventArgs(e.ListChangedType, e.NewIndex, new DataColumnPropertyDescriptor(col)); 
    /*Here is where VS breaks for the exception*/ onListChanged(this, newEventArg);
    } else {
         onListChanged(this, e); 
    }
} 

显然,如果在检查onListChanged之后出现问题!= = null。我怀疑在EndEdit方法期间更新DataRow会触发这一点。当然,一个简单的沙箱来隔离这个问题并没有为我重新定义错误。有没有其他人遇到这个bug,如果是这样,你是如何解决它的?

我现在的kludge是将MarketingContactIsFulltimeChangedHandler中的BeginInvoke调用到另一个在那里执行CreditLevel逻辑的方法。

0 个答案:

没有答案