2016-01-21 32 views
0

我有一個datagridview,在左邊有3個凍結列,然後是我希望總是顯示在右邊的第4列。剩餘的列顯示在第3列和第4列之間,並在其標題中編號(帶有1,2,3,4,...)。我允許用戶重新排列這些列,但我希望列標題保持數字順序。這個想法是,用戶應該看到它重新排列列中的數據,而不是列本身。第4列標記爲「新建」,如果用戶試圖將數據放入其中,則會創建一個新列並將數據添加到該列中,這是我始終希望它始終位於右側的一部分。datagridview索引越界事件中沒有設置索引時的錯誤

要做到這一點,我用下面的ColumnDisplayIndexChanged事件:

private void dgvTreeLevels_ColumnDisplayIndexChanged(object sender, DataGridViewColumnEventArgs e) { 
    switch(e.Column.Index) { 
     case 0: 
     case 1: 
     case 2: //prevents columns 0, 1, 2 from being reordered, (freezing just prevents them from being switched with 3+) 
      SynchronizationContext.Current.Post(delegate(object o) { 
      if (e.Column.DisplayIndex != e.Column.Index) e.Column.DisplayIndex = e.Column.Index; 
      }, null); 
      break; 
     case 3: //Displays always on the right 
      SynchronizationContext.Current.Post(delegate(object o) { 
      if (e.Column.DisplayIndex != dgvTreeLevels.Columns.Count - 1) 
       e.Column.DisplayIndex = dgvTreeLevels.Columns.Count - 1; 
      }, null); 
      break; 
     default: //Numbered columns 
      e.Column.HeaderText = (e.Column.DisplayIndex - 2).ToString(); 
      break; 
    } 
} 

大多數的正常工作時間。但偶爾線

   e.Column.HeaderText = (e.Column.DisplayIndex - 2).ToString(); 

正在thouing ArgumentOutOfRangeException聲明索引超出範圍。由於它沒有設置任何索引,這特別令人困惑。我無法可靠地創建錯誤。當我測試功能時,它只是偶爾彈出。我認爲這可能與試圖將編號列移到最右側有關,但隨着我在做其他事情時會出現錯誤。

在調試器中檢查顯示該行中的所有元素都已定義並且具有正確的值。我不知道爲什麼會出現錯誤。堆棧跟蹤爲

System.ArgumentOutOfRangeException was unhandled 
    Message="Index was out of range. Must be non-negative and less than the size of the collection.\r\nParameter name: index" 
    Source="mscorlib" 
    ParamName="index" 
    StackTrace: 
     at System.Collections.ArrayList.get_Item(Int32 index) 
     at System.Windows.Forms.DataGridViewColumnCollection.get_Item(Int32 index) 
     at System.Windows.Forms.DataGridView.GetColumnDisplayRectanglePrivate(Int32 columnIndex, Boolean cutOverflow) 
     at System.Windows.Forms.DataGridView.GetCellDisplayRectangle(Int32 columnIndex, Int32 rowIndex, Boolean cutOverflow) 
     at System.Windows.Forms.DataGridView.GetCellAdjustedDisplayRectangle(Int32 columnIndex, Int32 rowIndex, Boolean cutOverflow) 
     at System.Windows.Forms.DataGridView.InvalidateCellPrivate(Int32 columnIndex, Int32 rowIndex) 
     at System.Windows.Forms.DataGridView.OnColumnHeaderGlobalAutoSize(Int32 columnIndex) 
     at System.Windows.Forms.DataGridView.OnCellValueChanged(DataGridViewCellEventArgs e) 
     at System.Windows.Forms.DataGridViewColumnHeaderCell.SetValue(Int32 rowIndex, Object value) 
     at System.Windows.Forms.DataGridViewColumn.set_HeaderText(String value) 
     at Customizable_Reports.frmReport.dgvTreeLevels_ColumnDisplayIndexChanged(Object sender, DataGridViewColumnEventArgs e) 
     at System.Windows.Forms.DataGridView.FlushDisplayIndexChanged(Boolean raiseEvent) 
     at System.Windows.Forms.DataGridView.CorrectColumnDisplayIndexesAfterDeletion(DataGridViewColumn dataGridViewColumn) 
     at System.Windows.Forms.DataGridView.OnRemovedColumn_PreNotification(DataGridViewColumn dataGridViewColumn) 
     at System.Windows.Forms.DataGridViewColumnCollection.RemoveAtInternal(Int32 index, Boolean force) 
     at System.Windows.Forms.DataGridViewColumnCollection.RemoveAt(Int32 index) 
     at Customizable_Reports.frmReport.RemoveEmptyColumns() 
     at Customizable_Reports.frmReport.dgvTreeLevels_CellClick(Object sender, DataGridViewCellEventArgs e) 
     at System.Windows.Forms.DataGridView.OnMouseClick(MouseEventArgs e) 
     at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks) 
     at System.Windows.Forms.Control.WndProc(Message& m) 
     at System.Windows.Forms.DataGridView.WndProc(Message& m) 
     at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m) 
     at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam) 
     at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg) 
     at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(Int32 dwComponentID, Int32 reason, Int32 pvLoopData) 
     at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context) 
     at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context) 
     at Customizable_Reports.Program.Main() 
     at System.AppDomain._nExecuteAssembly(Assembly assembly, String[] args) 
     at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly() 
     at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) 
     at System.Threading.ThreadHelper.ThreadStart() 
    InnerException: 

回答

0

進一步的測試表明,當較高編號的列移到較低編號的列前面,然後刪除後,出現錯誤。當ColumnDisplayIndexChanged事件中的較低編號列的標題文本由於刪除而更新時,則會發生該錯誤。

您可以通過創建一個新的Winform應用程序來測試它,將一個datagridview放置在帶有兩列的窗體上,並允許用戶對它們進行重新排序。在塔1的前

private void button1_Click(object sender, EventArgs e) { 
    dataGridView1.Columns.RemoveAt(1); 
    } 

    private void dataGridView1_ColumnDisplayIndexChanged(object sender, DataGridViewColumnEventArgs e) { 
    e.Column.HeaderText = e.Column.DisplayIndex.ToString(); 
    } 

運行該應用程序,拖動柱2,然後按下按鈕:添加一個按鈕和以下兩個事件。請注意,有必要爲這個錯誤發生列的唯一標題。設置e.Column.HeaderText = "test";而不會產生錯誤。

對我來說,這看起來像是WinForms中的一個錯誤,而不是在這個編程中。但是我對確定的事情不夠了解。

傳遞命令到當前的同步上下文出現來解決這個問題:

SynchronizationContext.Current.Post(delegate(object o) { 
    e.Column.HeaderText = e.Column.DisplayIndex.ToString(); 
}, null);