InvalidOperationException - Когда заканчивается редактирование ячейки и перемещение к другой ячейке - PullRequest
3 голосов
/ 21 мая 2009

Я создал программу, в которой хотел вручную обновить представление таблицы данных. -У меня есть метод для обновления DGV, очистив его, а затем снова вставив данные. -Используя конструктор, я сделал обработчик событий для CellEndEdit DGV. Внутри обработчика событий данные обновляются и вызывается пользовательский метод обновления DGV.

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

InvalidOperationException Операция недопустима, поскольку она приводит к повторному вызову функции SetCurrentCellAddressCore.

Отладчик Visual C # отмечает строку, которая очищает данные: datagridview1.Rows.Clear ();

Если вы хотите воспроизвести проблему, создайте новый проект формы Windows с Visual C #, поместите объект DataGridView в форму и вставьте следующий код для Form1.cs:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace Error___DataGridView_Updating___Cell_endedit
{
    public partial class Form1 : Form
    {
        // Objects
        DataTable dt;
        DataColumn colID;
        DataColumn colName;
        DataColumn colInfo;
        // Constructor
        public Form1()
        {
            InitializeComponent();

            Initialize_dt();
            InsertSampleData_dt();
            Initialize_dataGridView1();
        }

        // Methods
        private void Initialize_dt()
        {
            dt = new DataTable();

            // Building Columns
            // ID
            colID = new DataColumn();
            colID.ColumnName = "ID";
            colID.DataType = typeof(int);
            dt.Columns.Add(colID);

            // Name
            colName = new DataColumn();
            colName.ColumnName = "Name";
            colName.DataType = typeof(string);
            dt.Columns.Add(colName);

            //Info
            colInfo = new DataColumn();
            colInfo.ColumnName = "Info";
            colInfo.DataType = typeof(string);
            dt.Columns.Add(colInfo);
        }

        private void InsertSampleData_dt()
        {            
            DataRow row; 

            // 0
            row = dt.NewRow();
            row["ID"] = 100;
            row["Name"] = "AAAA";
            row["Info"] = "First Record";
            dt.Rows.Add(row);

            //1
            row = dt.NewRow();
            row["ID"] = 101;
            row["Name"] = "BBBB";
            row["Info"] = "Second Record";
            dt.Rows.Add(row);


            //2
            row = dt.NewRow();
            row["ID"] = 102;
            row["Name"] = "CCCC";
            row["Info"] = "Third Record";
            dt.Rows.Add(row);
        }

        private void Initialize_dataGridView1()
        {
            dataGridView1.AllowUserToAddRows = false;

            // Data Grid Definitions
            //      Row Header

            dataGridView1.RowHeadersWidthSizeMode = DataGridViewRowHeadersWidthSizeMode.DisableResizing;
            dataGridView1.RowHeadersWidthSizeMode = DataGridViewRowHeadersWidthSizeMode.AutoSizeToAllHeaders;
            //      ColumnHeaders
            dataGridView1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells;

            // Building Columns
            #region ID
            {
                DataGridViewColumn colSGID = new DataGridViewTextBoxColumn();
                colSGID.Name = "ID";
                colSGID.HeaderText = "#";
                colSGID.ReadOnly = true;
                colSGID.Visible = false;
                colSGID.Resizable = DataGridViewTriState.False;

                dataGridView1.Columns.Add(colSGID);
            }
            #endregion

            #region Name
            {
                DataGridViewColumn colSGName = new DataGridViewTextBoxColumn();
                colSGName.Name = "Name";
                colSGName.HeaderText = "Name";

                dataGridView1.Columns.Add(colSGName);
            }
            #endregion

            #region Info
            {
                DataGridViewColumn colSGSubject = new DataGridViewTextBoxColumn();
                colSGSubject.Name = "Info";
                colSGSubject.HeaderText = "Description";

                dataGridView1.Columns.Add(colSGSubject);
            }
            #endregion

            Refresh_dataGridView1();
        }

        private void Refresh_dataGridView1()
        {
            int index;

            dataGridView1.SuspendLayout();

            dataGridView1.Rows.Clear();

            //MessageBox.Show("Cleared Data. Rebuilding...");

            foreach (DataRow row in dt.Rows)
            {
                index = dataGridView1.Rows.Add(new DataGridViewRow());

                dataGridView1.Rows[index].Cells["ID"].Value = row["ID"];
                dataGridView1.Rows[index].Cells["Name"].Value = row["Name"];
                dataGridView1.Rows[index].Cells["Info"].Value = row["Info"];

                //MessageBox.Show("row #" + index);
            }

            dataGridView1.ResumeLayout();
        }

        //Event Handlers
        private void dataGridView1_CellEndEdit(object sender, DataGridViewCellEventArgs e)
        {
            bool toUpdate = false;

            int id = (int)dataGridView1.Rows[e.RowIndex].Cells["ID"].Value;
            string columnName = dataGridView1.Columns[e.ColumnIndex].Name;
            string value = (string)dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex].Value;

            if (value == null)
            {
                value = string.Empty;
            }

            switch (columnName)
            {
                case "Name":
                    if (value == string.Empty)
                    {
                        MessageBox.Show("Name Can't Be Empty!");
                    }
                    else
                    {
                        toUpdate = true;
                    }
                    break;
                case "Info":
                    toUpdate = true;
                    break;
            }

            if (toUpdate)
            {
                foreach(DataRow row in dt.Rows)
                {
                    if ( (int)row["ID"] == id)
                    {
                        row[columnName] = value;
                    }
                }

                Refresh_dataGridView1();
            }

        }
    }
}

Ответы [ 3 ]

7 голосов
/ 27 мая 2009

На форуме MSDN есть ответ Брюса. Чжоу. Я разместил здесь фрагмент из него. Здесь также ссылка на оригинальный пост.

private void dataGridView1_CellEndEdit(object sender, DataGridViewCellEventArgs e)
{
    ...................................................;
    if (toUpdate)
    {
        foreach(DataRow row in dt.Rows)
        {
            if ( (int)row["ID"] == id)
            {
                row[columnName] = value;
            }
        }

        this.BeginInvoke(new MethodInvoker(Refresh_dataGridView1));
    }
}

...

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

1 голос
/ 23 января 2015

В последний час я ударился головой о клавиатуру, чтобы решить эту проблему. вот мой обходной путь: глядя на проблему: при выборе другой ячейки (или любого элемента управления в виде сетки) запускается EndEdit.

применить следующую проверку перед применением вашей правки:

public void myGrid_EndEdit(object sender, DataGridViewCellEventArgs e) 
{
  if (!myGrid.Rows[e.RowIndex].Cells[e.ColumnIndex].Selected)
                return;
  //...rest of your code to apply edit below...
}

Это должно применяться к любой редактируемой ячейке (таким образом, редактирование не применяется при потере фокуса; достаточно ввести Enter, чтобы применить редактирование)

0 голосов
/ 20 октября 2016

Моя работа заключалась в том, чтобы захватить событие CellMouseDown, и если действие было в ячейке, отличной от редактируемой, то оно выдает DataGridView.EndEdit (). Все остальное работает как положено.

...