Winforms: проблемы с проверкой ячейки в datagridview

#c# #.net #winforms #datagridview

#c# #.net #winforms #datagridview

Вопрос:

Я хочу проверить ячейку Winforms datagridview с помощью CellValidating. Если значение не было задано пользователем правильно, я устанавливаю ErrorText и использую e.Cancel , чтобы курсор оставался в ячейке. Теперь проблема в том, что символ ошибкитекст ошибки) не отображаются (в ячейке). Когда я удаляю e.Отмена, ячейка теряет фокус и отображается символ ошибки. Как я могу добиться того, чтобы ячейка оставалась в режиме редактирования, и символ ошибки тоже отображался?

 if (...)
{
   this.datagridviewX.Rows[e.RowIndex].Cells[e.ColumnIndex].ErrorText = "Errortext";
   e.Cancel = true;
}
else
{
   this.datagridviewX.Rows[e.RowIndex].Cells[e.ColumnIndex].ErrorText = "";
}
  

Комментарии:

1. Как я уже сказал в своем ответе — то, что вы описываете, не является готовым поведением, поэтому вы, должно быть, делаете что-то необычное. Не могли бы вы предоставить какой-нибудь код?

Ответ №1:

Поведение, которое вы видите, на самом деле связано с проблемой рисования, а не с тем, что значок ошибки не отображается. Происходит то, что при установке текста ошибки ячейки отображается значок, но текстовое поле ячейки в режиме редактирования закрашивается поверх значка, поэтому значок не отображается пользователю!

У вас есть два варианта для исправления этого — один из них — просто использовать текст ошибки строки, поэтому вместо:

 this.datagridviewX.Rows[e.RowIndex].Cells[e.ColumnIndex].ErrorText = "Errortext";  
e.Cancel = true;  
  

У вас есть:

 this.datagridviewX.Rows[e.RowIndex].ErrorText = "Errortext";
e.Cancel = true;
  

Другой вариант — изменить заполнение ячейки в ячейке (переместив элемент управления редактированием) и закрасить значок.

Я действительно нашел этот метод для решения проблемы здесь и воспроизвел их код ниже (на C # и не VB.Net ).

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

 void dataGridView1_CellValidating(object sender, DataGridViewCellValidatingEventArgs e)
{
    if (string.IsNullOrEmpty(e.FormattedValue.ToString()))
    {
        DataGridViewCell cell = dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex];

        cell.ErrorText =
            "Company Name must not be empty";

        if (cell.Tag == null)
        {
            cell.Tag = cell.Style.Padding;
            cell.Style.Padding = new Padding(0, 0, 18, 0);
        }
        e.Cancel = true;

    }
    else
    {
        dataGridView1.Rows[e.RowIndex].ErrorText = string.Empty;
    }
}
  

Это позволяет видеть значок, а не элемент управления редактированием, за исключением того, что значок тоже переместился! Поэтому нам также нужно нарисовать новый значок.

 void dataGridView1_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)
{
    if (dataGridView1.IsCurrentCellDirty)
    {
        if (!string.IsNullOrEmpty(e.ErrorText))
        {
            GraphicsContainer container = e.Graphics.BeginContainer();
            e.Graphics.TranslateTransform(18,0);
            e.Paint(this.ClientRectangle, DataGridViewPaintParts.ErrorIcon);
            e.Graphics.EndContainer(container);
            e.Handled = true;
        }
    }
}
  

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

 void dataGridView1_CellEndEdit(object sender, DataGridViewCellEventArgs e)
{
    if (!string.IsNullOrEmpty(dataGridView1[e.ColumnIndex, e.RowIndex].ErrorText))
    {
        DataGridViewCell cell = dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex];
        cell.ErrorText = string.Empty;
        cell.Style.Padding = (Padding)cell.Tag;
        cell.Tag = null;
    }
}
  

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

Я установил DataGridView.Покажите celltooltips = true и введите логическую ошибку, чтобы отслеживать, есть ли у нас ошибка редактирования. Затем я обрабатываю событие наведения курсора мыши:

 void dataGridView1_MouseHover(object sender, EventArgs e)
{
    if (inError)
    {                
        Point pos = this.PointToClient(Cursor.Position);               

        if (r.Contains(pos.X - 20, pos.Y - 5))
        {                   
            t.Show("There was an error", dataGridView1.EditingControl, 3000); 
        }
    }
}
  

t в этом коде представляет собой элемент управления всплывающей подсказкой на уровне формы, а r — прямоугольник.

Я заполняю r, как показано ниже, в обработчике рисования ячеек:

 void dataGridView1_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)
{
    if (dataGridView1.IsCurrentCellDirty)
    {
        if (!string.IsNullOrEmpty(e.ErrorText))
        {            
            GraphicsContainer container = e.Graphics.BeginContainer();

            r = dataGridView1.GetCellDisplayRectangle(e.ColumnIndex, e.RowIndex, true);
            e.Graphics.TranslateTransform(18, 0);
            e.Paint(this.ClientRectangle, DataGridViewPaintParts.ErrorIcon);
            e.Graphics.EndContainer(container);            

            e.Handled = true;
        }
    }
}
  

Меня не устраивают значения минус 20 и минус 5 в точке положения — это то, что я бы исправил, если бы у меня было немного больше времени.

Комментарии:

1. Я попробовал именно это с dataGridView1.Rows[e. RowIndex]. Ячейки[e. ColumnIndex].ErrorText = …

2. @Kottan предоставьте некоторый код (вероятно, лучший для всей формы, если не слишком большой), и мы можем посмотреть.

3. @Kottan — хорошо, теперь я тебя понял. В вашем вопросе вообще не было ясно, что вы устанавливаете ошибку в ячейке, а не в строке. Предоставление кода всегда полезно.

4. Это работает, если я использую только dataGridView1.Rows[e. RowIndex].Текст ошибки. Значок ошибки отображается в заголовке строки (не в ячейке).

5. Привет, у меня есть пользовательский редактор, размещенный в ячейке, и значок уведомления об ошибке не отображается в ячейке, он отображается в виде белой области, но при наведении курсора мыши на эту область отображается всплывающая подсказка. Однако при использовании стандартных datagridviewcolumns отображаются как значок уведомления об ошибке, так и всплывающая подсказка, так что не так? Я использую ApplyCellStyleToEditingControl для применения стиля ячейки к редактору, чтобы применить то же заполнение.