Back to Devexpress

Tutorial: Custom Drawing

windowsforms-114616-controls-and-libraries-data-grid-getting-started-walkthroughs-appearance-and-conditional-formatting-tutorial-custom-drawing.md

latest7.2 KB
Original Source

Tutorial: Custom Drawing

  • Dec 28, 2020
  • 5 minutes to read

This walkthrough is a transcript of the Custom Drawing video available on the DevExpress YouTube Channel.

In this tutorial, you will learn how to use the grid View’s CustomDraw… events. You’ll start with a grid displaying plain task data. First, you’ll use an event to customize the appearance of individual cells. Then, the same event handler will be modified to alter the displayed text in individual cells depending on grid data. You’ll then extend the handler even further to draw images within specific cells. Finally, you’ll see how to custom paint column headers while keeping their interactive elements, such as filter dropdown buttons and sort glyphs.

Starting Point

Start with an application that has a GridControl displaying task data.

Custom Drawing Individual Cells

Choose the grid View and handle the GridView.CustomDrawCell event. This event provides you with the RowCellCustomDrawEventArgs.RowHandle and RowCellCustomDrawEventArgs.Column parameters that identify the cell being painted.

  • Customizing Cell Appearance

  • Changing Cell Display Text

  • Displaying Custom Images within Cells

Custom Drawing Column Headers

To custom paint column headers, subscribe to the GridView.CustomDrawColumnHeader event. Use the gradient from ‘Salmon’ to ‘White’ to fill the background of column headers, and after that, display header captions. Set the event’s CustomDrawEventArgs.Handled parameter to true to prevent the default painting mechanism from being invoked when the event handler is completed.

csharp
private void gridView_CustomDrawColumnHeader(object sender, ColumnHeaderCustomDrawEventArgs e) {
    Rectangle rect = e.Bounds;
    // Create a new brush
    using (Brush brush = new LinearGradientBrush(e.Bounds, Color.Salmon, Color.White, LinearGradientMode.ForwardDiagonal)) {
        // Fill a column's background
        e.Cache.FillRectangle(brush, rect);
        // Draw the column's caption
        e.Appearance.DrawString(e.Cache, e.Info.Caption, e.Info.CaptionRect);
        e.Handled = true;
    }
}

Now run the application. Column headers are painted with the ‘Salmon’ to ‘White’ gradient.

However, the usual sort and filter glyphs are not displayed. There is a way to fix this and display standard interactive elements within column headers. You need to enumerate the ColumnHeaderCustomDrawEventArgs.Info .InnerElements collection and use a specially designed method to paint them if their settings indicate that they are currently visible.

csharp
private void gridView_CustomDrawColumnHeader(object sender, ColumnHeaderCustomDrawEventArgs e) {
    // ...
    // Draw the filter and sort buttons.
    foreach (DevExpress.Utils.Drawing.DrawElementInfo info in e.Info.InnerElements) {
        if (!info.Visible) continue;
        DevExpress.Utils.Drawing.ObjectPainter.DrawObject(e.Cache, info.ElementPainter, info.ElementInfo);
    }           
}

Run the application again to see the result. Now, the headers have a custom appearance while keeping the standard elements so end-users can still interact with column headers in the usual manner.

Complete Code

csharp
private void gridView_CustomDrawCell(object sender, DevExpress.XtraGrid.Views.Base.RowCellCustomDrawEventArgs e) {
    GridView view = sender as GridView;
    if (e.RowHandle == view.FocusedRowHandle) return;
    if (e.Column.FieldName != "UnitPrice") return;
    // Fill a cell's background if its value is greater than 30.
    if (Convert.ToInt32(e.CellValue) > 30)
        e.Appearance.BackColor = Color.FromArgb(60, Color.Salmon);
    // Specify the cell's display text. 
    double discount = Convert.ToDouble(view.GetRowCellValue(e.RowHandle, view.Columns["Discount"]));
    if (discount > 0) {
        double unitPrice = Convert.ToDouble(view.GetRowCellValue(e.RowHandle, view.Columns["UnitPrice"]));
        double discountPrice = unitPrice * (1 - discount);
        e.DisplayText = "Discount price: " + discountPrice.ToString("c2");
    }
    e.DefaultDraw();
    // Paint images in cells if discounts > 0.
    Image image = Image.FromFile("c:\\important.png");
    if (discount > 0)
        e.Cache.DrawImage(image, e.Bounds.Location);
}

private void gridView_CustomDrawColumnHeader(object sender, ColumnHeaderCustomDrawEventArgs e) {
    Rectangle rect = e.Bounds;
    // Create a new brush
    using (Brush brush = new LinearGradientBrush(e.Bounds, Color.Salmon, Color.White, LinearGradientMode.ForwardDiagonal)) {
        // Fill a column's background
        e.Cache.FillRectangle(brush, rect);
        // Draw the column's caption
        e.Appearance.DrawString(e.Cache, e.Info.Caption, e.Info.CaptionRect);
        e.Handled = true;
    }
    // Draw the filter and sort buttons.
    foreach (DevExpress.Utils.Drawing.DrawElementInfo info in e.Info.InnerElements) {
        if (!info.Visible) continue;
        DevExpress.Utils.Drawing.ObjectPainter.DrawObject(e.Cache, info.ElementPainter, info.ElementInfo);
    }
}

See Also

Custom Painting Basics

Custom Painting Scenarios

Elements that Can Be Custom Painted

Appearance and Conditional Formatting

Tutorial: View and Column Appearance

Tutorial: Custom Drawing

Tutorial: Conditional Formatting