DataGridView:编辑时更改编辑控件的大小

8
DataGridView 中,当我编辑单元格时,希望单元格的大小根据字符串长度自动扩展。 Excel 也是这样做的。
DataGridView 中,进入编辑模式时,会在单元格位置放置一个 DataGridViewTextBoxEditingControl。 我尝试更改此控件的边界/大小,但结果只是我期望大小的短暂闪烁。 它被直接覆盖了原始的、截断的方式。
有什么想法可以让这个工作起来吗?
谢谢,
Timo
7个回答

3
你需要先重写 DataGridViewCell.PositionEditingPanel 方法。你需要重新定义自己的列类型和单元格类型以访问此方法。
以下是一个示例,演示如何将编辑面板(拥有编辑控件的面板)的大小乘以2:
dataGridView1.AutoGenerateColumns = false; // disable columns auto generation

... add all columns

// add your special column
col = new MyColumn();
col.DataPropertyName = "Text"; // bind with the corresponding property
dataGridView1.Columns.Add(col); // add the custom column

... add other columns

public class MyCell : DataGridViewTextBoxCell
{
    public override Rectangle PositionEditingPanel(Rectangle cellBounds, Rectangle cellClip, DataGridViewCellStyle cellStyle, bool singleVerticalBorderAdded, bool singleHorizontalBorderAdded, bool isFirstDisplayedColumn, bool isFirstDisplayedRow)
    {
        cellBounds.Width *= 2;
        cellClip.Width = cellBounds.Width;
        return base.PositionEditingPanel(cellBounds, cellClip, cellStyle, singleVerticalBorderAdded, singleHorizontalBorderAdded, isFirstDisplayedColumn, isFirstDisplayedRow);
    }
}

public class MyColumn : DataGridViewTextBoxColumn
{
    public MyColumn()
    {
        CellTemplate = new MyCell();
    }
}

3
这个问题很旧了,但希望我的回答能帮助到一些人。我遇到了同样的问题,并能够使用类似以下过程使列宽随用户输入而动态更新,以确保文本适合列中。
所需事件:
- CellBeginEdit - CellEndEdit - EditingControlShowing - TextBoxKeyPressEvent (即KeyPress)
注意: 以下代码假定 AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells。
// ---------------------------------------------------------------------------

private void dataGridView1_CellBeginEdit(object sender, DataGridViewCellCancelEventArgs e)
{
    // Copies the original column width because switching to DataGridViewAutoSizeColumnMode.None
    // will automatically make the column a default width.
    int origColumnWidth = dataGridView1.Columns[e.ColumnIndex].Width;

    dataGridView1.Columns[e.ColumnIndex].AutoSizeMode = DataGridViewAutoSizeColumnMode.None;

    // Reverts back to the original width.
    dataGridView1.Columns[e.ColumnIndex].Width = origColumnWidth;
}

// ---------------------------------------------------------------------------

private void dataGridView1_CellEndEdit(object sender, DataGridViewCellEventArgs e)
{
    dataGridView1.Columns[e.ColumnIndex].AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells;
}

// ---------------------------------------------------------------------------

private void dataGridView1_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
{
    if (e.Control is TextBox)
    {
        var tbox = (e.Control as TextBox);

        // De-register the event FIRST so as to avoid multiple assignments (necessary to do this or the event
        // will be called +1 more time each time it's called).
        tbox.KeyPress -= TextBoxKeyPressEvent;
        tbox.KeyPress += TextBoxKeyPressEvent;
    }
}

// ---------------------------------------------------------------------------

private void TextBoxKeyPressEvent(object sender, KeyPressEventArgs e)
{
    // Gets the text prior to the new character being added.  Appending an arbitrary "0" to the value
    // to account for the missing character when determining appropriate measurements.
    string prevText = dataGridView1.CurrentCell.EditedFormattedValue.ToString() + "0";

    Graphics editControlGraphics = dataGridView1.EditingControl.CreateGraphics();

    // Gets the length of the current text value.
    SizeF stringSize = editControlGraphics.MeasureString(prevText, dataGridView1.EditingControl.Font);

    int widthForString = (int)Math.Round(stringSize.Width, 0);

    // Makes the column width big enough if it's not already.
    if (dataGridView1.CurrentCell.OwningColumn.Width < widthForString)
    {
        dataGridView1.CurrentCell.OwningColumn.Width = widthForString;
    }
}

编辑:更新 TextBoxKeyPressEvent 逻辑以考虑退格键:

private void TextBoxKeyPressEvent(object sender, KeyPressEventArgs e)
        {
            string prevText;
            bool wasBackspaced = false;

            // The following logic will either add or remove a character to/from the text string depending if the user typed
            // an additional character or pressed the Backspace key.  At the end of the day, the cell will (at least) be
            // sized to the configured minimum column width or the largest row width in the column because we're using 
            // AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells.
            if (e.KeyChar == Convert.ToChar(Keys.Back))
            {
                prevText = dataGridView1.CurrentCell.EditedFormattedValue.ToString();

                if (prevText.Length == 0)
                {
                    // Don't try to make it any smaller...
                    return;
                }

                // Remove an arbitrary character for determining appropriate measurements.
                prevText = prevText.Remove(prevText.Length - 1);
                wasBackspaced = true;
            }
            else
            {
                // Gets the text prior to the new character being added.  Appending an arbitrary "0" to the value
                // to account for the missing character when determining appropriate measurements.
                prevText = dataGridView1.CurrentCell.EditedFormattedValue.ToString() + "0";
            }

            Graphics editControlGraphics = dataGridView1.EditingControl.CreateGraphics();

            // Gets the length of the current text value.
            SizeF stringSize = editControlGraphics.MeasureString(prevText, dataGridView1.EditingControl.Font);

            int widthForString = (int)Math.Round(stringSize.Width, 0);

            // Makes the column width big, or small, enough if it's not already.
            if (dataGridView1.CurrentCell.OwningColumn.Width < widthForString ||  // 1. Applies when adding text
                (dataGridView1.CurrentCell.OwningColumn.Width > widthForString &&          // ---
                 dataGridView1.CurrentCell.OwningColumn.MinimumWidth < widthForString &&   // 2. Applies when backspacing
                 wasBackspaced))                                                           // ---
            {
                dataGridView1.CurrentCell.OwningColumn.Width = widthForString;
            }
        }

这里有几个问题(a,b,c)。 a) 它只能扩展而不能缩小,例如,如果我回删字符,则不会缩小,但实际上应该要缩小。 b) 如果我在单元格内回删,则该代码无法正常工作,它将回删视为任何普通字符,并扩展单元格一个字符,而我希望它能缩小单元格。 c) 如果我按“向前删除”,则TextBoxKeyPressEvent过程甚至不会触发。因此,它不会尝试缩小文本框。 - barlop
@barlop 您是正确的,我的原始示例没有考虑到退格键。我已经更新了我的帖子,并添加了如何处理它的其他代码。我最初指望控件根据最小宽度属性和AutoSizeColumnsMode设置为"AllCells"自动调整列宽,但这只会在提交编辑后发生。根据C点,您是正确的,必须使用KeyDown事件捕获删除键。在这里解释:https://dev59.com/kGsy5IYBdhLWcg3w-i_h - VineAndBranches
好的... 另一件值得纠正的事情是,使用 dataGridView1.CurrentCell.EditedFormattedValue 可能有点冒险,正如在这里提到的 http://stackoverflow.com/questions/3207777/datagridview-cell-turns-black-when-accessing-editedformattedvalue 也许更好的方法是使用 dataGridView1.EditingControl.Text - barlop

0
这对我很有用:
启用窗体的 KeyPreview 属性,并将窗体的 KeyPress 事件的主体更改为以下内容:
private void Form1_KeyPress(object sender, KeyPressEventArgs e)
{
            if (e.KeyChar!='\b')   //discard backspace
            {
              dataGridView1.Columns[0].Width += 5;  //the column's index or name

            }
            else
            {
                dataGridView1.Columns[0].Width -= 5;  //for backspase pressing
            }
}

你可以使用 e.KeyChar 限制按下的按键;


即使单元格为空或光标在最左侧时,当用户按下“删除”键时,单元格(甚至整个列)也会缩小。如果“删除”键没有删除字符,则它不应该真正缩小。 - barlop

0

我已经找到了几个解决方案

其中一个使用MeasureString和一个datagridview,另一个为了确定单元格的正确宽度而创建另一个datagridview,如果该单元格具有该内容,则另一个(我的最新的)使用一个datagridview进行管理,并添加和删除行。

这是使用第二个datagridview的方法

在表单上绘制一个datagridview,我给它两列没有数据。

代码将创建第二个datagridview,也有两列没有数据。

当然,提问者遇到的问题是,如果没有自动调整大小的编辑,不清楚要设置列的宽度。此解决方案创建另一个datagridview(称其为DGVb),这个datagridview未添加到表单中。并将数据写入DGVb中的单元格,查看单元格所占用的宽度,并将该数字用作设置适当DGV中的单元格的数字。

Vine提到的另一个问题是,如果将单元格设置为自动调整大小,就无法通过编程方式设置列的宽度。因此,您可以在触发cellbeginedit事件时放置代码,将autosize设置为none,并在触发cellendedit时重新启用它。另外一件事是,因为设置为none可能会立即使列的大小略微改变,例如,打开autosize的column1可能为73,然后当您关闭autosize时,它会变成100,因此您可以在将autosize设置为none之前存储大小,然后将autosize设置为none并将大小设置为原来的大小,以保留不需要的大小更改。这就是Vine所介绍的内容。

此代码可扩展和缩小列,并且不会出现使用backdelete、forward delete或箭头键的弱点,尽管在撰写本文时,Vine的答案在这些键方面存在一些弱点。我已经使用TextChanged来避免这些问题(而不是keydown等)。

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

namespace datagridviewexpandcelldynamically_with_second_dgv
{
    public partial class Form1 : Form
    {
        DataGridView dgvtest = new DataGridView();
        //  DataGridView dgvtest;

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {

                dataGridView1.AllowUserToAddRows = false;
                dgvtest.AllowUserToAddRows = false;

                dataGridView1.CellBeginEdit += (object ssender, DataGridViewCellCancelEventArgs ee) =>
                {
                    //keep column width as it is for now but just change autosize to none so will be able to manually increase it
                    int origColumnWidth = dataGridView1.Columns[ee.ColumnIndex].Width;
                    dataGridView1.Columns[ee.ColumnIndex].AutoSizeMode = DataGridViewAutoSizeColumnMode.None;
                    dataGridView1.Columns[ee.ColumnIndex].Width = origColumnWidth;
                };

                dataGridView1.CellEndEdit += (object sssender, DataGridViewCellEventArgs eee) =>
                {
                    dataGridView1.Columns[eee.ColumnIndex].AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells;
                };

                dataGridView1.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.AllCells;
                dataGridView1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells;

                dgvtest.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.AllCells;
                dgvtest.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells;


                dgvtest.Columns.Add("Column1", "Column1");
                dgvtest.Columns.Add("Column2", "Column2");

                dgvtest.Rows.Add(1);
                dataGridView1.Rows.Add(1);

                /*
                Form newfrm = new Form();
                newfrm.Show();
                newfrm.Controls.Add(dgvtest);
                dgvtest.Show();
                */

                //dgvtest.Rows[0].Cells[0].Value = "abc";


        }



        private void dataGridView1_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
        {

            if (e.Control is TextBox)
            {
                var tbox = (e.Control as TextBox);

                // De-register the event FIRST so as to avoid multiple assignments (necessary to do this or the event
                // will be called +1 more time each time it's called).

                tbox.TextChanged -= TextBoxChanged;
                tbox.TextChanged += TextBoxChanged;
                //not KeyDown 'cos the character has not appeared yet in the box. and one would have to check what it was as a parameter, and if it's a backdelete then go back one.. and also forward delete isn't coutned as a keydown.
                //not KeyUp 'cos while yeah the character has at least appeared, there's a delay so if you hold backdelete then only after releasing it will it trigger the procedure, and updating the width of the cell then is a bit late.
                //not KeyPress 'cos has issues of keyup. 

            }

        }


        private void TextBoxChanged(object sender, EventArgs e)
        {


            int colindex = dataGridView1.CurrentCell.ColumnIndex;


            int oldcolwidth = dataGridView1.CurrentCell.Size.Width;
            //string stredit=dataGridView1.CurrentCell.EditedFormattedValue.ToString();
            string stredit=dataGridView1.EditingControl.Text;
            dgvtest.Rows[0].Cells[0].Value = stredit;

            int newcolwidth = dgvtest.Rows[0].Cells[0].Size.Width;

            int headercellsize = dataGridView1.Columns[colindex].HeaderCell.Size.Width;

            // find biggest existing one
            int maxcellincol = headercellsize;

            int tempcelllength = 0;
            for (int i = 0; i < dataGridView1.Rows.Count; i++)
            {
                if (dataGridView1.Rows[i].Cells[colindex].Value == null) dataGridView1.Rows[i].Cells[colindex].Value = "";

                //length of all others but not current.
                tempcelllength = dataGridView1.Rows[i].Cells[colindex].Size.Width;

                if (tempcelllength > maxcellincol) maxcellincol = tempcelllength;
            }



            int diffcol = newcolwidth - oldcolwidth;

            // new isn't an ideal name.. 'cos it's not made new yet.. and 'cos if it's smaller than the max one then we won't make it the new one.. but it will be the new one if it's bigger than the max.

            // txtdesc.Text = "";
            txtdesc.Text += "newcolwidth=" + newcolwidth + "\r\n";
            txtdesc.Text += "maxcellincol=" + maxcellincol + "\r\n";


            //if (newcolwidth < maxcellincol)  != even if = then fine.

            dataGridView1.Columns[colindex].Width = newcolwidth;
            dataGridView1.Width += diffcol;

        } 

    }


}

扩展单元格文本输入时的想法相当巧妙,但看起来比这种另一种选择更可视化,虽然不太容易做到,但并不美观,即在cellbeginedit时扩展单元格大小(因此将其设置为autosize none,并将列宽设置为像= 50这样的某个大小),然后在cellendedit上将其缩小回原始大小-autosize-),然后我想在cellendedit上增加datagridview宽度,使其不出现滚动条。但是,数据网格视图列会突然变大,使用起来不太好看。

如果能够以某种方式克隆DataGridView,或者替代方案是复制带有字体的值,那么这个功能可以进一步改进,因为单元格的宽度取决于列中所有其他单元格的数据和字体。这个方法有效是因为第二个DataGridView具有与第一个相同的数据。 - barlop
实际上,第二个DataGridView只需要2个单元格。一个用于保存第一个DataGridView列中的最大值,另一个用于保存正在编辑的第一个DataGridView单元格的值。字体可以设置为与第一个DataGridView相应单元格的字体。 - barlop

0

我在另一个答案中提到了两个解决方案,这个是使用MeasureString方法的解决方案(与第二个DataGridView解决方案相对)。

任何关于textbox1-5.text等的提及都已被注释掉,只是为了调试。

这个解决方案和另一个解决方案不仅可以调整你正在编辑的列的大小,还可以调整DataGridView和窗体的宽度,但如果你不想要这种行为,你可以轻松地将其注释掉。

我应该使用“uses”关键字来创建图形对象,但无论如何。

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

namespace datagridviewexpandcelldynamically
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void dataGridView1_CellBeginEdit(object sender, DataGridViewCellCancelEventArgs e)
        {

            int origColumnWidth = dataGridView1.Columns[e.ColumnIndex].Width;

            dataGridView1.Columns[e.ColumnIndex].AutoSizeMode = DataGridViewAutoSizeColumnMode.None;

            dataGridView1.Columns[e.ColumnIndex].Width = origColumnWidth;

            if (dataGridView1.CurrentCell == null) dataGridView1.CurrentCell.Value = "";


        }

        private void dataGridView1_CellEndEdit(object sender, DataGridViewCellEventArgs e)
        {
            dataGridView1.Columns[e.ColumnIndex].AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells;
        }

        private void dataGridView1_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
        {

            if (e.Control is TextBox)
            {
                var tbox = (e.Control as TextBox);

                // De-register the event FIRST so as to avoid multiple assignments (necessary to do this or the event
                // will be called +1 more time each time it's called).

                tbox.TextChanged -= TextBoxChanged;
                tbox.TextChanged += TextBoxChanged;

            }

        }

        private void TextBoxChanged(object sender, EventArgs e)
        {

            // try catch is helpful in a winforms program 'cos otherwise program might just stop.
            // https://dev59.com/Y3I-5IYBdhLWcg3w-9wK

            try
            {
                int colindex = dataGridView1.CurrentCell.ColumnIndex;

                Graphics agraphics = this.CreateGraphics();

                SizeF headerTextSize = agraphics.MeasureString(dataGridView1.Columns[colindex].HeaderText, dataGridView1.EditingControl.Font);

                // sometimes it goes black and this link here says to use editing control http://stackoverflow.com/questions/3207777/datagridview-cell-turns-black-when-accessing-editedformattedvalue

                // string stredit=dataGridView1.CurrentCell.EditedFormattedValue.ToString();
                string stredit=myDataGridView.EditingControl.Text;
                SizeF curCellTextSize = agraphics.MeasureString(stredit, dataGridView1.EditingControl.Font);
                //SizeF curCellTextSize = agraphics.MeasureString(dataGridView1.CurrentCell.GetEditedFormattedValue.ToString(), dataGridView1.EditingControl.Font);
                int curCellTextSize_i = (int)Math.Round(curCellTextSize.Width, 0);

                int headerCellSize = dataGridView1.Columns[colindex].Width;

                textBox2.Text = headerTextSize.Width.ToString();
                textBox3.Text = headerCellSize.ToString();

                // find biggest existing one
                int maxcelltextincol = (int)Math.Round(headerTextSize.Width,0);
                // the max size, at least for the header, includes a bit of padding.. 
                maxcelltextincol += 20;
                int tempcelllength=0;
                for(int i=0; i<dataGridView1.Rows.Count;i++) {
                    if (dataGridView1.Rows[i].Cells[colindex].Value == null) dataGridView1.Rows[i].Cells[colindex].Value = "";

                    tempcelllength = (int)Math.Round(agraphics.MeasureString(dataGridView1.Rows[i].Cells[colindex].Value.ToString(), dataGridView1.EditingControl.Font).Width, 0);

                    if (tempcelllength > maxcelltextincol) maxcelltextincol = tempcelllength;       
                }


            //    textBox2.Text = "PRE curCellTextSize_i=" + curCellTextSize_i + " " + "dgvw=" + dataGridView1.Columns[colindex].Width.ToString() + " max=" + maxcelltextincol.ToString() +  " prevstringlength=";

                string txtinwhatiamediting = stredit;

                SizeF sizelengthoftxtinwhatiamediting = agraphics.MeasureString(txtinwhatiamediting, dataGridView1.Font); //intermediate
                int lengthoftxtinwhatiamediting=(int)Math.Round(sizelengthoftxtinwhatiamediting.Width,0);

                //if(lengthoftxtinwhatiamediting>maxcelltextincol) 
                int amountovermax = lengthoftxtinwhatiamediting - maxcelltextincol;    


                int oldcolwidth = dataGridView1.Columns[colindex].Width;
                if (amountovermax < 0) { dataGridView1.Columns[colindex].Width = maxcelltextincol; return; }


                dataGridView1.Columns[colindex].Width = maxcelltextincol + amountovermax;
                int newcolwidth = dataGridView1.Columns[colindex].Width;
                   //dataGridView1.Width += (int)Math.Round((double)amountovermax,0);
                dataGridView1.Width += newcolwidth - oldcolwidth;
                this.Width += newcolwidth - oldcolwidth;
                //   textBox2.Text = "curCellTextSize_i=" + curCellTextSize_i + " " + "dgvw=" + dataGridView1.Columns[colindex].Width.ToString() + " max=" + maxcellincol.ToString();

                if (curCellTextSize_i > maxcelltextincol) maxcelltextincol = curCellTextSize_i;

                  // textBox5.Text= "POST curCellTextSize_i=" + curCellTextSize_i + " " + "dgvw=" + dataGridView1.Columns[colindex].Width.ToString() + " max=" + maxcelltextincol.ToString() + "prevstring=" + prevString + " prevstringlength=" + prevtextsize + " diff=" + diff;
                 //  textBox5.Text = "POST curCellTextSize_i=" + curCellTextSize_i + " " + "dgvw=" + dataGridView1.Columns[colindex].Width.ToString() + " max=" + maxcelltextincol.ToString() + " diff=" + amountovermax;


            }
            catch (Exception ee) { MessageBox.Show(ee.ToString()); }                                
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            try
            {
                //dataGridView1.AllowUserToAddRows = false;
                dataGridView1.Font = new System.Drawing.Font("David", 30.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
                dataGridView1.Rows.Add(1);

                dataGridView1.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.AllCells;
                dataGridView1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells;                

                Graphics g = this.CreateGraphics(); // should be in a using.

                Font fontA = new System.Drawing.Font("David", 30.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));

                SizeF headerSize = g.MeasureString(dataGridView1.Columns[0].HeaderText, fontA);

                int totalcolwidth = dataGridView1.RowHeadersWidth + 40; // about 40+70
                //MessageBox.Show(totalcolwidth.ToString());
                for (int i = 0; i < dataGridView1.Columns.Count; i++)
                    totalcolwidth += dataGridView1.Columns[i].Width;

              //  MessageBox.Show(totalcolwidth.ToString());
              //  MessageBox.Show(dataGridView1.Width.ToString());
                int diff = totalcolwidth - dataGridView1.Width;
                dataGridView1.Width = totalcolwidth;
              //  MessageBox.Show(dataGridView1.Width.ToString());
                this.Width += diff;

            }
            catch (Exception exc)
            {
                MessageBox.Show("exception ");
                MessageBox.Show(exc.ToString());
            }
        }


    }
}

0

这个解决方案(我的最新版本)使用了与使用2个datagridview的答案类似的技术,但它只使用一个datagridview来管理。

当在单元格中输入文本时,它会创建一个新行,并将该文本输入到该行中相应的列中。然后它会查看新宽度应该是多少,并将该列扩展到该宽度并删除该行。

这是我之前的编辑,对其进行了改进。因为事实证明我可以注释掉cellbeginedit和cellendedit方法。而且还发现,虽然之前的版本很好,但稍作修改就会导致黑色单元格的错误,这在这里提到了。只要我自动调整所有列,我就可以避免黑色单元格。(还有使用EditingControl.Text,就像我现在做的一样)

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


namespace dgveditresize
{
    public partial class Form1 : Form
    {

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {

            //DGVprocs.dgv = dataGridView1;
            dataGridView1.AllowUserToAddRows = false;

            autoshrinkwholedgv();

            //DGVprocs.autoshrink_off_wholedgv__preservewidths(); not necessary
            dataGridView1.Rows.Add(5);
            //dataGridView1.CellBeginEdit += OnCellBeginEditExpandCol;

             dataGridView1.EditingControlShowing += DataGridView1_EditingControlShowing;

          //  MessageBox.Show(dataGridView1.Columns[1].Width.ToString());
        }


        private void DataGridView1_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
        {

           // MessageBox.Show(dataGridView1.Columns[1].Width.ToString());



            // http://stackoverflow.com/questions/37505883/how-can-i-dynamically-detect-the-characters-in-a-datagridview-cell-execute-co

            //if(DGVprocs.isshrinkon()==false) { MessageBox.Show("err ")}

            if (e.Control is TextBox)
            {
                var tbox = (e.Control as TextBox);

                // De-register the event FIRST so as to avoid multiple assignments (necessary to do this or the event
                // will be called +1 more time each time it's called).

                tbox.TextChanged -= A_Cell_TextChanged;
                tbox.TextChanged += A_Cell_TextChanged;
            }



        }

        private void A_Cell_TextChanged(object sender, EventArgs e)
        {

            dataGridView1.Rows.Add(1);

            //MessageBox.Show(dataGridView1.Rows.Count+" rows");

            int colindex = dataGridView1.CurrentCell.ColumnIndex;


            int oldcolwidth = dataGridView1.CurrentCell.Size.Width;
            //string stredit=dataGridView1.CurrentCell.EditedFormattedValue.ToString();
            string stredit = dataGridView1.EditingControl.Text;

            //dgvtest.Rows[0].Cells[0].Value = stredit;
            dataGridView1.Rows[dataGridView1.Rows.Count - 1].Cells[dataGridView1.CurrentCell.ColumnIndex].Value = stredit;
            //MessageBox.Show(dataGridView1.Rows.Count + " rows");
            //int newcolwidth = dgvtest.Rows[0].Cells[0].Size.Width;

            //autoshrinkcurrentcol(); // WORSE   (1)  WW
            autoshrinkwholedgv(); //added BETTER (2)  XX
            int newcolwidth = dataGridView1.Rows[dataGridView1.Rows.Count - 1].Cells[dataGridView1.CurrentCell.ColumnIndex].Size.Width;
            autoshrinkoff_wholedgv_preservewidths(); //added BETTER (3) YY
           // autoshrink_off_currentcol_preservewidth(); // WORSE (4)  ZZ
             /*               
             WAS ERROR WITH THIS ONE..
             IF YOU TYPE IN THE FIRST CELL THEN HIT DOWN ARROW TWICE
             THEN TYPE THEN IT GOES BLACK
             BUT PROBLEM RESOLVED  SINCE USING 2,3 RATHER THAN 1,4                    
              */
            // doing either  1,4  or 2,3
            // no comparison
            // 1,4 causes blackness.
            // 2,3 and it works
            // all of them is just same as 2,3 not surprising.
            // but funny that 1,4 causes blackness.


            //MessageBox.Show("removing row");

            if(dataGridView1.AllowUserToAddRows) { MessageBox.Show("programmer msg- issue in 'cell's textchanged method', allowusertoaddrows must be false otherwise an exception is thrown by the next line dataGridView1.Rows.RemoveAt(dataGridView1.Rows.Count - 1);"); Application.Exit(); }
                // requires user not add row set to true.
                dataGridView1.Rows.RemoveAt(dataGridView1.Rows.Count - 1);

            //MessageBox.Show(dataGridView1.Rows.Count + " rows");

            int headercellsize = dataGridView1.Columns[colindex].HeaderCell.Size.Width;

            // find biggest existing one
            int maxcellincol = headercellsize;

            int tempcelllength = 0;
            for (int i = 0; i < dataGridView1.Rows.Count; i++)
            {
                if (dataGridView1.Rows[i].Cells[colindex].Value == null) dataGridView1.Rows[i].Cells[colindex].Value = "";

                //length of all others but not current.
                tempcelllength = dataGridView1.Rows[i].Cells[colindex].Size.Width;

                if (tempcelllength > maxcellincol) maxcellincol = tempcelllength;
            }



            int diffcol = newcolwidth - oldcolwidth;

            // new isn't an ideal name.. 'cos it's not made new yet.. and 'cos if it's smaller than the max one then we won't make it the new one.. but it will be the new one if it's bigger than the max.

             txtdesc.Text = "";
            txtdesc.Text += "newcolwidth=" + newcolwidth + "\r\n";
            txtdesc.Text += "maxcellincol=" + maxcellincol + "\r\n";


            //if (newcolwidth < maxcellincol)  != even if = then fine.

            // say we move that earlier
            //dataGridView1.Rows.RemoveAt(dataGridView1.Rows.Count - 1);

            //DGVprocs.autoshrinkoff_preservecurrentcolwidth();


            //if (dataGridView1.Columns[colindex].Width == newcolwidth)
            if (oldcolwidth == newcolwidth)
            txtwidthcomp.Text="old width is equal to cur width diff="+diffcol;
            else
                txtwidthcomp.Text="old width is not equal to cur width diff="+diffcol;

            //shrink should never be on while there's an editbox showing.
            //if (diffcol>0) if (DGVprocs.isshrinkon() == true) MessageBox.Show("shrink is on this may be why it's not resizing");
            // when turning autoshrink off a)it should be done after the editbox it will freeze the editbox to the size that it was. b)when it is done it should be done in a preservational way. getting all col sizes beforehand and turning shrink off and setting all cols to that size that they were 
            // DGVprocs.autoshrinkoff();
            // shrink has to be off for the current column.. doesn't matter about the rest of it.
            // if(diffcol>0) if(DGVprocs.isshrinkoncurrentcol()==true) MessageBox.Show("shrink is on(cur col) this may be why it's not resizing");



            dataGridView1.Columns[colindex].Width = newcolwidth;
            dataGridView1.Width += diffcol;


            // i think autoshrink while the editbox is showing is wrong.
            // you need to autoshrink it to size of editbox.
//            DGVprocs.autoshrink();


        }


        public void autoshrinkwholedgv()
        {

            dataGridView1.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.AllCells;
            dataGridView1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells;

            return;
        }

        public void autoshrinkcurrentcol()
        {

            dataGridView1.Columns[getcurrentcol()].AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells;

            //this may be optional.
            dataGridView1.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.AllCells;

            // DGVprocs.dgv.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells;

            return;
        }

        public int getcurrentcol()
        {
            if (dataGridView1.CurrentCell == null) { MessageBox.Show("Programmer msg - getcurrentcol() error, current cell not selected"); Application.Exit(); }
            if (dataGridView1.CurrentCell.Value == null) dataGridView1.CurrentCell.Value = "";

            return dataGridView1.CurrentCell.ColumnIndex;
        }

        public void autoshrink_off_currentcol_preservewidth()
        {
            int w =  dataGridView1.Columns[getcurrentcol()].Width;
            dataGridView1.Columns[getcurrentcol()].AutoSizeMode = DataGridViewAutoSizeColumnMode.None;
            dataGridView1.Columns[getcurrentcol()].Width = w;
        }

        public void autoshrinkoff_wholedgv_preservewidths()
        {
            // deal with the 73,100 bug.. whereby if you ave autoresize on immediately, then a DGV with Column1 Colum2, Column3 e.t.c. has width of 73. But then when turning autoresize off it goes to 100. 

            int[] colsizes = new int[dataGridView1.Columns.Count];

            for (int i = 0; i < dataGridView1.Columns.Count; i++)
                colsizes[i] = dataGridView1.Columns[i].Width;

            dataGridView1.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.None;
            dataGridView1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.None;

            for (int i = 0; i < dataGridView1.Columns.Count; i++)
                dataGridView1.Columns[i].Width = colsizes[i];


            return;
        }

    }


}

上述代码似乎没有解决黑色单元格问题,但对代码进行轻微修改以使用行WW和ZZ将导致解决该问题。这看起来像是datagridview的一个错误,并在此处提到 https://connect.microsoft.com/VisualStudio/feedback/details/2878864/datagridview-cell-goes-black,类似的错误在此处提到http://stackoverflow.com/questions/3207777/datagridview-cell-turns-black-when-accessing-editedformattedvalue - barlop

-1
你想要单元格在输入时自动调整大小吗?还是希望在输入文本并按下回车后再调整大小?第二个选项是最简单的。
请告诉我。
谢谢。

4
不要问另一个问题,你可能应该直接回答你所描述的两种方式,或者在问题上发表评论。 - Sumo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接