DataGridView: изменить размер элемента управления редактирования при редактировании - PullRequest
8 голосов
/ 26 марта 2009

в DataGridView Я хочу, чтобы размер ячейки увеличивался в соответствии с длиной строки при редактировании ячейки. Excel делает то же самое.

В DataGridView , при входе в режим редактирования, DataGridViewTextBoxEditingControl помещается в положение ячейки. Я попытался изменить границы / размер этого элемента управления, но в результате я получил лишь короткое мерцание желаемого размера. Он прямо перекрашивается оригинальным, усеченным способом.

Есть идеи, как заставить это работать?

Спасибо

Timo

Ответы [ 7 ]

3 голосов
/ 17 мая 2014

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

Используемые события:

  • 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 для учета Backspace:

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;
            }
        }
2 голосов
/ 25 августа 2011

Вам нужно начать с переопределения метода 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();
    }
}
0 голосов
/ 30 июня 2016

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

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

Это редактирование того, что у меня было, и это улучшает его ... Поскольку оказалось, что я могу закомментировать методы 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;
        }

    }


}
0 голосов
/ 31 мая 2016

Я уже упоминал в своем другом ответе, что у меня есть два решения, это решение MeasureString (в отличие от второго решения datagridview)

любое упоминание textbox1-5.text e.t.c. было прокомментировано, что это было только для отладки.

это и другое решение не только изменяют размер столбца, в котором вы редактируете, но также изменяют ширину представления данных и ширину формы, хотя вы можете легко это прокомментировать, если не хотите такого поведения. *

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

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.
            // http://stackoverflow.com/questions/1583351/silent-failures-in-c-seemingly-unhandled-exceptions-that-does-not-crash-the-pr

            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 голосов
/ 31 мая 2016

Я нашел несколько решений для этого

Один использует MeasureString и одно представление сетки данных, другое создает другое представление сетки данных с целью определения правильной ширины ячейки, если в ячейке должно быть это содержимое. Другой (мой последний) управляет им с помощью одного обзора данных, добавляя и удаляя строку.

Это тот, который использует второе представление данных

Нарисуйте сетку в форме, которую я дал моим двум столбцам без данных.

Код создаст второе представление данных также с двумя столбцами без данных.

Конечно, вопрос, с которым столкнулся спрашивающий, заключался в том, что без автоматического изменения размера редактирования неясно, какую ширину задать столбцу. Это решение создает другое представление данных (назовите его DGVb), которое не добавлено в форму. И он записывает эти данные в ячейку в DGVb, видит, какую ширину заняла ячейка, и использует эту цифру в качестве цифры для установки ячейки в надлежащем DGV.

Еще одна проблема, связанная с виноградной лозой, заключается в том, что, если для ячейки задано автоматическое изменение размера, вы не можете программно устанавливать ширину столбца, поэтому вы можете включить код при срабатывании события cellbeginedit, установить для автоматического изменения значение none и поместить его обратно при срабатывании cellendedit, и еще одна вещь, потому что установка в none может немедленно изменить размер столбца, например Параметр column1 с включенным автоматическим изменением может быть 73, а затем при выключении автоматического изменения размера он становится равным 100, так что вы можете сохранить размер до того, как вы установите автоматический размер равным none, затем установите автоматический размер равным none и установите размер таким, какой он был, сохраняя нежелательное изменение размера. Это то, что сделано здесь, как описано в Vine.

этот код расширяет и сжимает столбец и не имеет слабых мест с клавишами обратного удаления, удаления вперед или стрелками, хотя на момент написания сообщения в лозе были некоторые недостатки с этими клавишами. Я использовал TextChanged, чтобы избежать этих проблем. (в отличие от keydown e.t.c.)

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 и установите ширину col в некоторый размер, например = 50), и уменьшите ее до размера - autosize - для cellendedit), а затем я полагаю на cellendedit для увеличения ширины datagridview поэтому он не получает полосу прокрутки. Но тогда столбец datagridview скачет в размере, и это не очень удобно для использования.

0 голосов
/ 30 августа 2011

Это была работа для меня:

Включить 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;

0 голосов
/ 26 августа 2009

Хотели бы вы, чтобы размер ячейки изменялся при вводе? Или вы хотите изменить его размер после ввода текста и ввода? Второй вариант по правде говоря самый простой.

Дайте мне знать.

Спасибо

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