Winforms: проблемы проверки ячейки в представлении данных - PullRequest
7 голосов
/ 10 октября 2011

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

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 Ответ

11 голосов
/ 10 октября 2011

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

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

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.ShowCellToolTips = true и ввел логическое inError для отслеживания, если у нас в настоящее время есть ошибка редактирования.Затем я обрабатываю событие MouseHover:

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

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