InvalidOperationException - عند إنهاء تحرير الخلية والانتقال إلى خلية أخرى

StackOverflow https://stackoverflow.com/questions/893752

سؤال

قمت بإجراء برنامج أردت فيه تحديث طريقة عرض شبكة البيانات يدويا. لدي طريقة لتحديث DGV عن طريق مسحها ثم إعادة إدخال البيانات. - استخدام المصمم، لقد قمت بمعالج حدث للميلزلي DGV. داخل معالج الأحداث، يتم تحديث البيانات ويتم استدعاء البيانات المنعشة مخصص DGV.

أثناء تشغيل البرنامج، كلما بدأت تحرير خلية وإنهاءه عن طريق تحديد موقع آخر، يتم طرح استثناء:

InvalidOperationException العملية غير صالحة لأنه يؤدي إلى استدعاء Reentrant إلى وظيفة SetCurrentCellAddressCore.

يصادف مصحح الأخطاء Visual C # الخط الذي يمسح البيانات: DataGridView1.rows.glear ()؛

إذا كنت ترغب في إعادة إنشاء المشكلة، فقم بإجراء مشروع Windows NOMS جديد مع Visual C #، ضع كائن DataGridView على النموذج، ولصق التعليمات البرمجية التالية للنظامي.

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();
            }

        }
    }
}
هل كانت مفيدة؟

المحلول

هناك إجابة بواسطة Bruce.zhou في منتديات 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));
    }
}

...

عند استخدام هذا الإصلاح، كلما تم تحديد الخلية الجديدة، يتم تحديد جميع الخلايا بينها وبين الخلية الأولى (بما في ذلك). أنا أبحث عن وسيلة لتحديد الخلية الجديدة فقط.

نصائح أخرى

طرقت رأسي على لوحة المفاتيح لمدة ساعة الماضية لحل هذه المشكلة. هنا الحل الخاص بي: النظر في المشكلة: عند تحديد خلية أخرى (أو أي عنصر تحكم داخل GridView) يتم تشغيل 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...
}

يجب أن ينطبق هذا على أي خلية يتم تحريرها. (وبالتالي لا يتم تطبيق التحرير عند فقدان التركيز؛ سوف يكفي كتابة إدخال الدخول لتطبيق التعديل)

كان عملي حوله هو التقاط حدث الرجيلي، وإذا كان الإجراء على خلية أخرى غير التي يتم تحريرها، فإنها تصدر DataGridView.dentitit (). كل شيء آخر يعمل كما هو متوقع.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top