DataGrid генерирует исключение IndexOutOfRangeException из CurrencyManager при нажатии любой ячейки - PullRequest
4 голосов
/ 18 октября 2011

У меня есть сетка данных на форме окон.

Когда я первоначально обновляю эту сетку, чтобы она содержала данные, а затем щелкаю по ней, я получаю следующее исключение.

Примечательно, что исключение глубоко в обработке окон формы, и, таким образом, исключение обнаруживается в тот момент, когда я запускаю форму.

Обратите внимание, мне пришлось поставить галочку «Показать внешний код» в стеке вызовов, чтобы показать стек вызовов ниже, в противном случае он просто показывает [Внешний код].

Что касается догадок / шагов по устранению неполадок, полагая, что это могло быть вызвано сообщением, которое сработало для выбранного элемента, а затем для элемента, который теперь выбран, я попытался .SelectAll(); на DataGridView после обновления данных это дало те же результаты.

Исключение:

IndexOutOfRangeException
{"Index -1 does not have a value."}

Стек вызовов:

System.Windows.Forms.dll!System.Windows.Forms.CurrencyManager.this[int].get(int index) + 0xa1 bytes 
System.Windows.Forms.dll!System.Windows.Forms.CurrencyManager.Current.get() + 0x16 bytes    
System.Windows.Forms.dll!System.Windows.Forms.DataGridView.DataGridViewDataConnection.OnRowEnter(System.Windows.Forms.DataGridViewCellEventArgs e) + 0x101 bytes    
System.Windows.Forms.dll!System.Windows.Forms.DataGridView.OnRowEnter(ref System.Windows.Forms.DataGridViewCell dataGridViewCell = null, int columnIndex = 1, int rowIndex = 0, bool canCreateNewRow, bool validationFailureOccurred) + 0x218 bytes 
System.Windows.Forms.dll!System.Windows.Forms.DataGridView.SetCurrentCellAddressCore(int columnIndex = 1, int rowIndex = 0, bool setAnchorCellAddress, bool validateCurrentCell, bool throughMouseClick = true) + 0x59f bytes   
System.Windows.Forms.dll!System.Windows.Forms.DataGridView.OnCellMouseDown(System.Windows.Forms.DataGridView.HitTestInfo hti, bool isShiftDown, bool isControlDown) + 0x12db bytes  
System.Windows.Forms.dll!System.Windows.Forms.DataGridView.OnCellMouseDown(System.Windows.Forms.DataGridViewCellMouseEventArgs e) + 0x318 bytes 
System.Windows.Forms.dll!System.Windows.Forms.DataGridView.OnMouseDown(System.Windows.Forms.MouseEventArgs e) + 0x153 bytes 
System.Windows.Forms.dll!System.Windows.Forms.Control.WmMouseDown(ref System.Windows.Forms.Message m, System.Windows.Forms.MouseButtons button, int clicks) + 0xcf bytes    
System.Windows.Forms.dll!System.Windows.Forms.Control.WndProc(ref System.Windows.Forms.Message m) + 0x86e bytes 
System.Windows.Forms.dll!System.Windows.Forms.DataGridView.WndProc(ref System.Windows.Forms.Message m) + 0x92 bytes 
System.Windows.Forms.dll!System.Windows.Forms.Control.ControlNativeWindow.OnMessage(ref System.Windows.Forms.Message m) + 0x10 bytes    
System.Windows.Forms.dll!System.Windows.Forms.Control.ControlNativeWindow.WndProc(ref System.Windows.Forms.Message m) + 0x31 bytes  
System.Windows.Forms.dll!System.Windows.Forms.NativeWindow.DebuggableCallback(System.IntPtr hWnd, int msg = 513, System.IntPtr wparam, System.IntPtr lparam) + 0x57 bytes   
[Native to Managed Transition]  
[Managed to Native Transition]  
System.Windows.Forms.dll!System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(int dwComponentID, int reason = 4, int pvLoopData = 0) + 0x24e bytes  
System.Windows.Forms.dll!System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(int reason = 4, System.Windows.Forms.ApplicationContext context = {System.Windows.Forms.Application.ModalApplicationContext}) + 0x177 bytes 
System.Windows.Forms.dll!System.Windows.Forms.Application.ThreadContext.RunMessageLoop(int reason, System.Windows.Forms.ApplicationContext context) + 0x61 bytes    
System.Windows.Forms.dll!System.Windows.Forms.Application.RunDialog(System.Windows.Forms.Form form) + 0x33 bytes    
System.Windows.Forms.dll!System.Windows.Forms.Form.ShowDialog(System.Windows.Forms.IWin32Window owner) + 0x373 bytes    

Ответы [ 4 ]

6 голосов
/ 19 октября 2011

В конце концов проблема была решена путем использования универсального BindingList в качестве источника данных, а не универсального List.

Так как значения в источнике данных необходимо было изменить в ответ на взаимодействие пользователя с формой, мы заново заполняли список и снова прикрепляли его каждый раз, когда он менялся (когда он был List<>).

После реализации INotifyPropertyChanged на объекте в списке мы использовали BindingList<> и теперь привязываем данные один раз и обновляем при необходимости.

Хотя я до сих пор не знаю, почему использование списка вызывало проблемы, я рад, что у меня есть работоспособное решение.

1 голос
/ 18 октября 2011

, если вы обрабатываете события клика в коде, сделайте правильную проверку перед выполнением любой задачи.

if (e.ColumnIndex == 1) // check for correct column 
{
    if (e.RowIndex >= 0) // check for valied row index
    {
        DataGridViewRow dataGridViewRow = dataGridView1.Rows[e.RowIndex];
        // do stuff like update delete..
    }
}
0 голосов
/ 23 апреля 2018

Лучший подход, если вы добавите пользовательское событие DataError ко всем вашим DataGridViews, которые у вас есть на Form, и вы сможете отловить ошибку.

Просто попробуйте.

private void DataGridView1_DataError(object sender, DataGridViewDataErrorEventArgs e)
{

}
0 голосов
/ 14 мая 2017

Кажется, он где-то хранит старый список и пытается что-то обновить для нового объекта.Вы можете обойти это, воссоздав список, например:

// Get old list
List<BoardRow> rows = (List<BoardRow>)rowsDataGridView.DataSource;

// Add new row
rows.Add(form.boardRow);

// Re-create list
List<BoardRow> rowsNew = new List<BoardRow>(rows.Count);
rowsNew.AddRange(rows);

// Rebind source
this.rowsDataGridView.DataSource = rowsNew;

Не очень эффективно, но все еще работает, если вам нужен грязный хак для небольших наборов данных.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...