代码之家  ›  专栏  ›  技术社区  ›  B. Clay Shannon-B. Crow Raven

为什么此阵列列表删除代码失败?

  •  0
  • B. Clay Shannon-B. Crow Raven  · 技术社区  · 10 年前

    我试图通过传递相应的文本,在列表框中查找并删除该项,从列表框中删除特定值。使用此代码:

    private void UpdateGUIAfterTableSend(String listboxVal)
    {
        ExceptionLoggingService.Instance.WriteLog("Reached frmMain.UpdateGUIAfterTableSend");
        try
        {
            listBoxWork.DataSource = null; // <= It seems necessary to set this to null to circumvent "Value does not fall within the expected range"
            for (int i = listBoxWork.Items.Count - 1; i >= 0; --i)
            {
                if (listBoxWork.Items[i].ToString().Contains(listboxVal))
                {
                    listBoxWork.Items.RemoveAt(i);
                }
            }
        }
        catch (Exception ex)
        {
            String msgInnerExAndStackTrace = String.Format("{0}; Inner Ex: {1}; Stack Trace: {2}", ex.Message, ex.InnerException, ex.StackTrace);
            ExceptionLoggingService.Instance.WriteLog(String.Format("From frmMain.UpdateGUIAfterTableSend: {0}", msgInnerExAndStackTrace));
        }
    }
    

    尽管如此,它还是失败了;问题记录为:

    Date: 2/10/2015 1:48:07 PM
    Message: Reached frmMain.UpdateGUIAfterTableSend
    
    Date: 2/10/2015 1:48:07 PM
    Message: From application-wide exception handler: System.InvalidOperationException: InvalidOperationException
       at System.Collections.ArrayList.ArrayListEnumeratorSimple.MoveNext()
       at HHS.frmMain.SendDeliveries()
       at HHS.frmMain.menuItemSEND_Deliveries_Click(Object sender, EventArgs e)
       at System.Windows.Forms.MenuItem.OnClick(EventArgs e)
       at System.Windows.Forms.Menu.ProcessMnuProc(Control ctlThis, WM wm, Int32 wParam, Int32 lParam)
       at System.Windows.Forms.Form.WnProc(WM wm, Int32 wParam, Int32 lParam)
       at System.Windows.Forms.Control._InternalWnProc(WM wm, Int32 wParam, Int32 lParam)
       at Microsoft.AGL.Forms.EVL.EnterMainLoop(IntPtr hwnMain)
       at System.Windows.Forms.Application.Run(Form fm)
       at HHS.Program.Main()
    

    注意,记录异常的是“应用程序范围的异常处理程序”,而不是UpdateGUIAfterTableSend()中的catch块

    通过如下设置其数据源来填充列表框:

    listBoxWork.DataSource = workTables;
    

    workTables是由查询填充的字符串列表:

    List<String> workTables = hhsdbutils.GetWorkTableNames();
    

    我很困惑是什么导致了问题(及其解决方案),以及UpdateGUIAfterTableSend()中的catch块为什么没有记录正在抛出的异常。

    更新

    在Steve的评论之后,我取消了将数据源设置为null的注释。则例外情况是:

    Date: 2/10/2015 2:19:58 PM
    Message: From frmMain.UpdateGUIAfterTableSend: Value does not fall within the expected range.; Inner Ex: ; Stack Trace:    at System.Windows.Forms.ListBox._VerifyNoDataSource()
       at System.Windows.Forms.ListBox.ObjectCollection.RemoveAt(Int32 index)
       at HHS.frmMain.UpdateGUIAfterTableSend(String listboxVal)
    

    更新2

    对于Adi Lester:

    private void SendDeliveries()
    {
        ExceptionLoggingService .Instance.WriteLog("Reached frmMain.SendDeliveries");
        Cursor curse = Cursor.Current;
        Cursor.Current = Cursors.WaitCursor;
        try
        {
            bool firstRecord = false;
            bool lastRecord = false;
            foreach (String tblname in listBoxWork.Items)
            {
                // Ignore INV tables
                if (tblname.IndexOf("INV") == 0) continue; 
                String tblSiteNum = hhsdbutils.GetSiteNumForTableName(tblname);
                String fileName = HHSUtils.GetGeneratedDSDFileName(tblSiteNum);
                String xmlData = hhsdbutils.GetDSDDataAsXMLFromTable(tblname, fileName);
                String uri = String.Format("{0}delivery/sendXML/duckbill/platypus/{1}", HHSConsts.BASE_REST_URL, fileName);
                fileXferImp = HHSConsts.GetFileTransferMethodology();
                fileXferImp.SendDataContentsAsXML(uri, xmlData, tblname, siteNum, firstRecord, lastRecord);
                String tableRefVal = HHSUtils.GetTableRefValForTableName(tblname, "DSD");
                hhsdbutils.DeleteTableReference(tableRefVal, "DSD");
                hhsdbutils.DropTable(tblname, tblSiteNum); // <- Will actually do this only after creating replacement tables in code
                UpdateGUIAfterTableSend(tblname);
            }
        }
        finally
        {
            Cursor.Current = curse;
        }
    }
    
    3 回复  |  直到 10 年前
        1
  •  2
  •   Sriram Sakthivel    10 年前

    你的两种方法都是错误的。我的意思是两者都设置 DataSource 设置为null,并从中删除项 ListBox 直接地

    当ListBox是数据绑定时(即 数据来源 set)不能修改 Items 直接收集。您必须删除基础数据源中的项。数据源应通知数据绑定引擎删除项,以便ListBox项保持同步。

    为此,您的 数据来源 应支持更改通知。如果是WPF,请使用 ObservableCollection 。如果是winforms,请使用 BindingList<T> .

    因此,您的代码应该如下所示:

    for (int i = yourDataSource.Count - 1; i >= 0; --i)
    {
        if (yourDataSource[i].ToString().Contains(listboxVal))
        {
            yourDataSource.RemoveAt(i);
        }
    }
    
        2
  •  1
  •   Steve    10 年前

    设置ListBox的DataSource时,请使用BindingSource,而不是直接使用 List(Of String) 这是必需的,否则绑定引擎将看不到DataSource中的任何更改。

    假设您想用类似这样的内容设置列表框项目,并想删除包含字符串“Test”的每个项目:

    listBoxWork = new ListBox();
    List<string> elements = new List<string>()
    {
        "Test1", "Test2", "Test3", "Example1", "Example2"
    };
    
    BindingSource bs = new BindingSource();
    bs.DataSource = elements;
    listBoxWork.DataSource = bs;
    

    现在,在尝试删除项的代码中使用

    private void UpdateGUIAfterTableSend(String listboxVal)
    {
        ExceptionLoggingService.Instance.WriteLog("Reached frmMain.UpdateGUIAfterTableSend");
        try
        {
            BindingSource bs = listBoxWork.DataSource as BindingSource;
            for (int i = bs.Count - 1; i >= 0; --i)
            {
                if (bs[i].ToString().Contains("Test"))
                {
                    bs.RemoveAt(i);
                }
            }
        }
        catch (Exception ex)
        {
            String msgInnerExAndStackTrace = String.Format("{0}; Inner Ex: {1}; Stack Trace: {2}", ex.Message, ex.InnerException, ex.StackTrace);
            ExceptionLoggingService.Instance.WriteLog(String.Format("From frmMain.UpdateGUIAfterTableSend: {0}", msgInnerExAndStackTrace));
        }
    }
    
        3
  •  1
  •   Stilgar    10 年前

    虽然您没有提供引发异常的实际代码,但很明显,您正在从正在枚举的列表中删除一个项(可能是通过foreach)。如果集合发生更改,则标准集合会使任何枚举器无效。在for循环中删除不是问题,这就是为什么您没有在那里捕获异常的原因。这个方法似乎是在foreach循环中的另一个方法中调用的。