Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Разработка Windows Forms > Обработчики событий DataGrid


Автор: tos84 26.12.2009, 17:21
C# изучаю недавно, так что если вопрос глупый, сильно не пинайте. 
Как из обработчика одного события  вызвать обработчик другого события?
Есть два события data grida – CellMouseEnter и CellPainting
Есть код, но он не работает так как хотелось бы. Закрашивается только стартовая ячейка.

Код

        int curRow = 0, curCol = 0;
        private void dataGridView1_CellMouseEnter(object sender, DataGridViewCellEventArgs e)
        {
            curRow = e.RowIndex; curCol = e.ColumnIndex;
        }

        public void dataGridView1_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)
        {
            if (e.ColumnIndex == curCol && e.RowIndex == curRow)
            {
                Brush backBrush = new SolidBrush(Color.Green); //заливка
                
                // Закрашиваем ячейку
                e.Graphics.FillRectangle(backBrush, e.CellBounds);

                e.Handled = true;
            }
        }


А хотелось бы, чтобы когда мышка наводится на ячейку, в curRow и curCol записывались номер столбца и строки, а затем эти значения передавались в обработчик события CellPainting.
Если написать вот так, то не работает, выдает ошибку.

Код

        private void dataGridView1_CellMouseEnter(object sender, DataGridViewCellEventArgs e)
        {
            curRow = e.RowIndex; curCol = e.ColumnIndex;
            dataGridView1_CellPainting(sender, e)
        }




Автор: tol05 26.12.2009, 18:03
а почему бы так не сделать?
Код

private void dataGridView1_CellMouseEnter(object sender, DataGridViewCellEventArgs e)
{
    dataGridView1[e.ColumnIndex, e.RowIndex].Style.BackColor = Color.Red;
}

private void dataGridView1_CellMouseLeave(object sender, DataGridViewCellEventArgs e)
{
    dataGridView1[e.ColumnIndex, e.RowIndex].Style.BackColor = dataGridView1.DefaultCellStyle.BackColor;
}

Автор: tos84 26.12.2009, 21:11
Этот вариант не подходит. Вопрос вытекает http://forum.vingrad.ru/forum/topic-285113.html, т.к. простого способа не нашлось, значит надо перерисовать ячейку и на нее добавить текст из этой ячейки с помощью e.Graphics.DrawString.
Например для одной ячейки это будет выглядеть так:

Код

        public void dataGridView1_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)
        {
            if (e.ColumnIndex == curCol && e.RowIndex == curRow)
            {
                Brush backBrush = new SolidBrush(Color.Green);            //заливка
                Pen gridPen = new Pen(dataGridView1.GridColor, 1);        //перо для грида
 
                // Точки для окантовки ячейки
                Point[] points ={
                                 new Point(e.CellBounds.Left-1, e.CellBounds.Top-1),
                                 new Point(e.CellBounds.Left-1, e.CellBounds.Bottom-1),
                                 new Point(e.CellBounds.Right-1, e.CellBounds.Bottom-1),
                                 new Point(e.CellBounds.Right-1, e.CellBounds.Top-1),
                                 new Point(e.CellBounds.Left-1, e.CellBounds.Top-1)
                                };
                
                // Закрашиваем ячейку
                e.Graphics.FillRectangle(backBrush, e.CellBounds);

                // Рисуем окантовку
                e.Graphics.DrawLines(gridPen, points);

                // Рисуем текст
                if (e.Value != null)
                {
                    e.Graphics.DrawString(
                                          e.Value.ToString(),
                                          e.CellStyle.Font,
                                          Brushes.Red,
                                          e.CellBounds.X + 1,
                                          e.CellBounds.Y + 4,
                                          StringFormat.GenericDefault
                                         );
                }

                e.Handled = true;
            }//end if
        }


Более жизненный пример, есть БД данные из которой отображаются в датагриде. БД обновляется.
Нам, к примеру, надо чтобы в первой колонке, на заднем фоне, в зависимости от значения в этой ячейке рисовался еще один прямоугольник, пропорциональный этому значению.
Вот код:

Код

         public void dataGridView1_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)
        {
            Pen gridPen = new Pen(dataGridView1.GridColor, 1);       //перо для грида
            Brush backBrush = new SolidBrush(Color.Aqua);            //заливка для фона
            Brush recBrush = new SolidBrush(Color.YellowGreen);      //заливка для прямоугольника

            int cellValue, rectWidth;

            //Проходимся по всем ячейкам в первой колонке 
            for (curRow = 0; curRow < dataGridView1.RowCount; curRow++) 
            {
                if (e.RowIndex == curRow && e.ColumnIndex == 0)
                {
                    // Расчитываем размер закрашиваемого прямоугольника
                    cellValue = Convert.ToInt32( dataGridView1.Rows[curRow].Cells[0].Value );
                    rectWidth = cellValue * e.CellBounds.Width / 10000 ;

                    // Точки для прямоугольника окантовки ячейки
                    Point[] points ={
                                     new Point(e.CellBounds.Left-1, e.CellBounds.Top-1),
                                     new Point(e.CellBounds.Left-1, e.CellBounds.Bottom-1),
                                     new Point(e.CellBounds.Right-1, e.CellBounds.Bottom-1),
                                     new Point(e.CellBounds.Right-1, e.CellBounds.Top-1),
                                     new Point(e.CellBounds.Left-1, e.CellBounds.Top-1)
                                    };

                    // Закрашиваем ячейку
                    e.Graphics.FillRectangle(backBrush, e.CellBounds);

                    // Закрашиваем часть ячейки
                    e.Graphics.FillRectangle(
                                             recBrush, 
                                             e.CellBounds.Left, e.CellBounds.Top,
                                             rectWidth, e.CellBounds.Height
                                            );
                        
                    // Рисуем окантовку
                    e.Graphics.DrawLines(gridPen, points);

                    
                    // Рисуем текст
                    if (e.Value != null)
                    {
                        e.Graphics.DrawString(
                                              e.Value.ToString(), e.CellStyle.Font, Brushes.Black,
                                              e.CellBounds.X + 1, e.CellBounds.Y + 4,
                                              StringFormat.GenericDefault
                                             );
                    }
                    e.Handled = true;
                }
            }//endfor
        }


Тут уже без перерисовки ячейки не обойтись.

Рисунок для наглядности.
http://radikal.ru/F/s59.radikal.ru/i164/0912/f6/c24c377c36eb.jpg.html

Автор: tol05 26.12.2009, 22:11
тогда так попробуйте
Код

private void dataGridView1_CellMouseEnter(object sender, DataGridViewCellEventArgs e)
{
    if (e.RowIndex >= 0 && e.ColumnIndex >= 0)
    //это вызовет OnPaint для данной ячейки
    dataGridView1.InvalidateCell(dataGridView1[e.ColumnIndex, e.RowIndex]);
}

Автор: tos84 26.12.2009, 23:48
Спасибо за подсказку! Работает.  smile 
Только как сделать чтобы когда мышка выходит из этой ячейки, она становилась тогоже цвета что и была до этого, сообразить не могу.
Зато нашел большой http://msdn.microsoft.com/ru-ru/library/7fb61s43.aspx, там вместо закраски рамка, будем разбираться.

Автор: tol05 27.12.2009, 00:17
Цитата(tos84 @  26.12.2009,  22:48 Найти цитируемый пост)
Только как сделать чтобы когда мышка выходит из этой ячейки, она становилась тогоже цвета что и была до этого, сообразить не могу.

Код

private void dataGridView1_CellMouseLeave(object sender, DataGridViewCellEventArgs e)
{
    if (e.RowIndex >= 0 && e.ColumnIndex >= 0)
    {
        dataGridView1[e.ColumnIndex, e.RowIndex].Style.BackColor = dataGridView1.DefaultCellStyle.BackColor;
    }
}
только проблема в том, что при выходе из ячейки опять вызовется OnPaint для ячейки )
Т.е. нужно вводить дополнительные условия (флаги) в Paint.. чтобы при вхождении мыши в ячейку и при ее "уходе" ячейка получала разные цвета

Автор: tos84 27.12.2009, 09:46
Получилось.  smile 
При входе в клетку, она подсвечивается, при выходе, становится такой, как и была до этого.
Код

        int curRow, curCol;
        bool cellIn;

        private void dataGridView1_CellMouseEnter(object sender, DataGridViewCellEventArgs e)
        {
            cellIn = true;
            curRow = e.RowIndex; curCol = e.ColumnIndex;

            if (e.RowIndex >= 0 && e.ColumnIndex >= 0)
            {
                dataGridView1.InvalidateCell(dataGridView1[e.ColumnIndex, e.RowIndex]);
            }
        }

        private void dataGridView1_CellMouseLeave(object sender, DataGridViewCellEventArgs e)
        {
            cellIn = false;
            curRow = e.RowIndex; curCol = e.ColumnIndex;

            if (e.RowIndex >= 0 && e.ColumnIndex >= 0)
            {
                dataGridView1.InvalidateCell(dataGridView1[e.ColumnIndex, e.RowIndex]);
            }
        }

        private void dataGridView1_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)
        {
            Brush FonBrush = new SolidBrush(Color.Yellow);              //заливка для фона
    
            if (e.ColumnIndex == curCol && e.RowIndex == curRow && cellIn == true)
            {
                // Закрашиваем ячейку
                e.Graphics.FillRectangle(
                                         FonBrush,
                                         e.CellBounds.Left, e.CellBounds.Top,
                                         e.CellBounds.Width - 1, e.CellBounds.Height - 1
                                        );

                // Рисуем текст
                if (e.Value != null)
                {
                    e.Graphics.DrawString(
                                          e.Value.ToString(),
                                          e.CellStyle.Font,
                                          Brushes.Black,
                                          e.CellBounds.X + 1,
                                          e.CellBounds.Y + 4,
                                          StringFormat.GenericDefault
                                         );
                }
                e.Handled = true;
            }
        }


Только я не могу понять КАК это работает. Когда мышка заходит в клетку и она закрашивается, это понятно. Но когда выходит - откуда берется цвет фона по умолчанию?
Ну да ладно, главное что работет. smile 

Плюсы такого решения:
Не "мерцают" другие клетки, при изменении цвета ячейки, как при использовании .Style.BackColor для грида.
Вместо сплошной закраски, можно изобразить что-то свое, хоть рамку двойную.
Простота и понятность, даже для новичка, по сравнению с http://msdn.microsoft.com/ru-ru/library/7fb61s43.aspx

Думаю эта тема пригодится многим. Прикрепляю полностью готовый пример.

tol05, еще раз спасибо за помощь.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)