DataGridView: Как сделать так, чтобы ключ ввода добавил новую строку вместо изменения текущей ячейки? - PullRequest
8 голосов
/ 08 января 2010

Как мне заставить клавишу Enter вести себя в Winforms DataGridViewTextBoxCell, как в обычной Winforms TextBox (добавить новую строку в текст вместо изменения текущей ячейки)?

Ответы [ 3 ]

9 голосов
/ 10 января 2010

Ну, я узнал, как решить проблему. Сначала создайте класс с именем CustomDataGridViewTextBoxEditingControl, который наследуется от DataGridViewTextBoxEditingControl, и переопределите EditingControlWantsInputKey следующим образом:

public class CustomDataGridViewTextBoxEditingControl : DataGridViewTextBoxEditingControl
    {
        public override bool EditingControlWantsInputKey(
        Keys keyData, 
        bool dataGridViewWantsInputKey)
        {
            switch (keyData & Keys.KeyCode)
            {
                case Keys.Enter:
                    // Don't let the DataGridView handle the Enter key.
                    return true;
                default:
                    break;
            }

            return base.EditingControlWantsInputKey(keyData, dataGridViewWantsInputKey);
    }
}

Это останавливает DataGridView от вручения клавиши Enter и изменения текущей ячейки. Однако это не заставляет клавишу Enter добавлять новую строку. (Похоже, что DataGridViewTextBoxEditingControl удалил функциональность клавиши Enter). Поэтому нам нужно переопределить OnKeyDown и реализовать функциональность самостоятельно, например так:

protected override void OnKeyDown(KeyEventArgs e)
{
    switch (e.KeyCode & Keys.KeyCode)
    {
        case Keys.Enter:
            int oldSelectionStart = this.SelectionStart;
            string currentText = this.Text;

            this.Text = String.Format("{0}{1}{2}",
                currentText.Substring(0, this.SelectionStart),
                Environment.NewLine,
                currentText.Substring(this.SelectionStart + this.SelectionLength));

            this.SelectionStart = oldSelectionStart + Environment.NewLine.Length;
            break;
        default:
            break;
    }

    base.OnKeyDown(e);
}

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

public class CustomDataGridViewTextBoxCell : DataGridViewTextBoxCell
{
    public override Type EditType
    {
        get
        {
            return typeof(CustomDataGridViewTextBoxEditingControl);
        }
    }
}

После того, как вы это сделаете, вы можете установить для свойства CellTemplate в существующем столбце значение CustomDataGridViewTextBoxCell или создать класс, производный от DataGridViewColumn с предустановкой CellTemplate в CustomDataGridViewTextBoxCell, и вы будет все готово!

5 голосов
/ 09 января 2010

Это можно сделать, установив для свойства DataGridViewCellStyle.WrapMode значение true. Из MSDN:

Если WrapMode имеет значение False для ячейки, которая содержит текст, ячейка отображает текст в одну строку и отображает любые встроенные символы новой строки как поле персонажи. Если WrapMode Истина для ячейка, содержащая текст, ячейка отображает символы новой строки в виде строки ломает, но также оборачивает любые строки, которые превышать ширину ячейки.

Вы можете установить это для определенных ячеек, используя свойство Style в ячейке, или для всех ячеек в столбце, используя DefaultCellStyle для столбца.

[Обновление] Чтобы выборочно отключить ключ ввода в DataGridView, добавьте фильтр сообщений в форму, содержащую DataGridView, как показано ниже:

private KeyMessageFilter m_filter = null;

private void Form1_Load(object sender, EventArgs e)
{
    m_filter = new KeyMessageFilter(this); 
    Application.AddMessageFilter(m_filter);

}

Вот класс фильтра сообщений:

public class KeyMessageFilter : IMessageFilter
{
    private Form m_target = null;

    public KeyMessageFilter(Form targetForm)
    {
        m_target = targetForm;
    }

    private const int WM_KEYDOWN = 0x0100;

    private const int WM_KEYUP = 0x0101;


    public bool PreFilterMessage(ref Message m)
    {
        if (m.Msg == WM_KEYDOWN)
        {
            //Note this ensures Enter is only filtered if in the 
            // DataGridViewTextBoxEditingControl and Shift is not also  pressed.
            if (m_target.ActiveControl != null && 
                m_target.ActiveControl is DataGridViewTextBoxEditingControl && 
                (Keys)m.WParam == Keys.Enter && 
                (Control.ModifierKeys & Keys.Shift) != Keys.Shift)
            {
                return true;
            }

        }

        return false;
    }
}

Теперь клавиша Enter отключена при редактировании текста, и вы должны нажать клавишу табуляции, чтобы перейти к следующей ячейке. Shift + Enter по-прежнему добавляет новую строку к тексту, который вы редактируете.

Надеюсь, это поможет.

0 голосов
/ 11 января 2019

Хотя @Zach Johnson ответил на основную часть этого вопроса, его код не работал для меня. Потратив долгое время и прочитав разные темы, я понял, что вам также нужно установить некоторые свойства, чтобы получить эту работу. Итак, вот полный код, поэтому вы можете запустить пример: Определить CustomDataGridViewTextBoxCell:

class CustomDataGridViewTextBoxCell: DataGridViewTextBoxCell
{
    public override Type EditType => typeof(CustomDataGridViewTextBoxEditingControl);
}

Тогда определите класс CustomDataGridViewTextBoxEditingControl

class CustomDataGridViewTextBoxEditingControl : DataGridViewTextBoxEditingControl
{
    public override bool EditingControlWantsInputKey(
        Keys keyData,
        bool dataGridViewWantsInputKey)
    {
        switch (keyData & Keys.KeyCode)
        {
            case Keys.Enter:
                // Don't let the DataGridView handle the Enter key.
                return true;
            default:
                break;
        }

        return base.EditingControlWantsInputKey(keyData, dataGridViewWantsInputKey);
    }
    protected override void OnKeyDown(KeyEventArgs e)
    {
        switch (e.KeyCode & Keys.KeyCode)
        {
            case Keys.Enter:
                int oldSelectionStart = this.SelectionStart;
                string currentText = this.Text;

                this.Text = String.Format("{0}{1}{2}",
                    currentText.Substring(0, this.SelectionStart),
                    Environment.NewLine,
                    currentText.Substring(this.SelectionStart + this.SelectionLength));

                this.SelectionStart = oldSelectionStart + Environment.NewLine.Length;
                break;
            default:
                break;
        }

        base.OnKeyDown(e);
    }

}

Затем определите DataGridViewRolloverCell:

public class DataGridViewRolloverCell : DataGridViewTextBoxCell
{
    public override Type EditType => typeof(CustomDataGridViewTextBoxEditingControl);
}

После этого определить класс DataGridViewCustomColumn:

public class DataGridViewCustomColumn : DataGridViewColumn
{
    public DataGridViewCustomColumn()
    {
        this.CellTemplate = new CustomDataGridViewTextBoxCell();
    }
}

Теперь, если у вас есть DatagridViewControl с именем dgv, ваш код будет выглядеть так:

DataGridViewCustomColumn col =  new DataGridViewCustomColumn();
dgv.Columns.Add(col);

Сейчас важно : Вам все еще нужно установить в DefaultCellStyle свойство WrapText до true. Сделайте это в конструкторе или с помощью этого кода:

DataGridViewCellStyle dataGridViewCellStyle1 = DataGridViewCellStyle();
dataGridViewCellStyle1.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft;
dataGridViewCellStyle1.ForeColor = System.Drawing.SystemColors.ControlText;
dataGridViewCellStyle1.WrapMode = System.Windows.Forms.DataGridViewTriState.True;
this.dgv.DefaultCellStyle = dataGridViewCellStyle1;

И не забудьте установить для свойства Datagridview.AutoSizeRowsMode значение AllCells. Тогда это будет работать.

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