# Owner Drawing

Better ListView: Ultimate .NET ListView replacement control for WinForms (C#, VB.NET)
Download More Info

Owner drawing allow to customize appearance of any element, element part and the control itself:

## Drawing Over Control Parts

The simple way to draw over control parts is by using drawing events:

- DrawBackground

- DrawColumnHeader

- DrawColumnHeaderBackground

- DrawGroup

- DrawGroupBackground

- DrawItem

- DrawItemBackground

Each of these events contains System.Drawing.Graphics object in event data with which custom drawing is possible. Areas of drawing are also provided. For example, to draw inside item inner area, there is a BetterListViewDrawItemEventArgs.ItemBounds.BoundsInner property containing the rectangle.

If you want to paint outside element areas, set OptimizedInvalidation property to false. This will ensure your custom drawing code will be called in every redraw cycle.

## Replacing Default Drawing by Custom Drawing

Owner drawing events are always called after the default drawing, so it is possible only to draw over exisiting drawing. When you need turn off some painting and do your own drawing instead of the default one (e.g. draw rotated text instead the straight one), you have to create your custom control inheriting from BetterListView:

C#

    class OwnerDrawBetterListView : BetterListView
    {
        // ...
    }

Visual Basic

    Class OwnerDrawBetterListView Inherits BetterListView
        ' ...
    End Class

Then you can override one of the drawing methods:

- OnDrawBackground

- OnDrawColumnHeader

- OnDrawGroup

- OnDrawGroupBackground

- OnDrawItem

- OnDrawItemBackground

This gives you more control over the painting, because your drawing code can be called before or after the default drawing, depending on where and if you call base implementation.

Every part of the default drawing has a switch so you can turn the default drawing off. For example, if you want not to draw default text on some item, set BetterListViewDrawItemEventArgs.DrawText property to false.

It is also possible to do custom drawing as the very last drawing of the whole control. To do this, override DrawingRedrawCore method and do your drawing after calling the base implementation:

C#

    protected override void DrawingRedrawCore(Graphics grfx)
    {
        base.DrawingRedrawCore(grfx);

        // do your custom drawing
    }

Visual Basic

    Protected Overrides Sub DrawingRedrawCore(grfx As Graphics)

        MyBase.DrawingRedrawCore(grfx)

        ' do your custom drawing

    End Sub

## Overriding Item and Control States

The appearance of element depends not only on its state, but also on the control state.

If you override one of the drawing methods (e.g. OnDrawItem), you can modify event data before calling base class implementation (e.g. base.OnDrawItem).

For example, BetterListViewDrawItemEventArgs contains ItemStateInfo property. By modifying this property, you can force drawing item in any state you wish.

BetterListViewDrawItemEventArgs also contains two properties regarding control state:

- DrawEnabled

  - Draw item as if the control is in enabled state (BetterListView.Enabled is true).

- DrawFocused

  - Draw item as if the control in in focused state (BetterListView.Focused is true).

By default, these properties correspond to actual control's state, but they can be modified. For example, one may want to set DrawFocused to true on every item that is selected, so the item will be highlighted even if the control loses focus.

The control state properties are available only in the BetterListViewItemEventArgs, but element states can be modified in all painting event handlers (also column headers and groups).

## Sample Source Code

The following sample shows owner drawing of item background:

C#

    this.listView.BeginUpdate();

    this.listView.Items.Add("Item with owner-drawn image and background.");

    this.listView.View = BetterListViewView.Tile;
    // turn off automatic image sizing to make space for image even when items do not have any images set
    this.listView.LayoutOptions = (BetterListViewLayoutOptions.Auto & ~BetterListViewLayoutOptions.AutoSizeItemImage);
    // set 4-pixel boundary around image
    this.listView.LayoutItemsCurrent.ImagePadding = new Padding(4);
    // set image size to be 50 by 50 pixels (it is possible to set image sizes for sub-items as well by adding more Size instances in the collection)
    this.listView.LayoutItemsCurrent.ImageSizes = new ReadOnlyCollection<Size>(new[] { new Size(50, 50) });

    this.listView.EndUpdate();

    // we would like to draw over item's foreground (custom image)
    this.listView.DrawItem += ListViewDrawItem;
    // we would like to draw over item's background
    this.listView.DrawItemBackground += ListViewDrawItemBackground;

Visual Basic

    ListView.BeginUpdate()

    ListView.Items.Add("Item with owner-drawn image and background.")

    ListView.View = BetterListViewView.Tile
    ' turn off automatic image sizing to make space for image even when items do not have any images set
    ListView.LayoutOptions = (BetterListViewLayoutOptions.Auto And Not BetterListViewLayoutOptions.AutoSizeItemImage)
    ' set 4-pixel boundary around image
    ListView.LayoutItemsCurrent.ImagePadding = New Padding(4)
    ' set image size to be 50 by 50 pixels (it is possible to set image sizes for sub-items as well by adding more Size instances in the collection)
    ListView.LayoutItemsCurrent.ImageSizes = New ReadOnlyCollection(Of Size)(New Size() {New Size(50, 50)})

    ListView.EndUpdate()

    ' we would like to draw over item's foreground (custom image)
    AddHandler ListView.DrawItem, AddressOf ListViewDrawItem
    ' we would like to draw over item's background
    AddHandler ListView.DrawItemBackground, AddressOf ListViewDrawItemBackground

DrawItem event handler draws on the item image area:

C#

    void ListViewDrawItem(object sender, BetterListViewDrawItemEventArgs eventArgs)
    {
        eventArgs.Graphics.SmoothingMode = SmoothingMode.HighQuality;

        Pen pen = new Pen(Color.BlueViolet, 2.5f);

        // draw ellipse in the image area
        eventArgs.Graphics.DrawEllipse(
            pen,
            eventArgs.ItemBounds.SubItemBounds[0].BoundsImage);

        pen.Dispose();
    }

Visual Basic

    Sub ListViewDrawItem(ByVal sender As Object, ByVal eventArgs As BetterListViewDrawItemEventArgs)

        eventArgs.Graphics.SmoothingMode = SmoothingMode.HighQuality

        Dim pen As New Pen(Color.BlueViolet, 2.5F)

        ' draw ellipse in the image area
        eventArgs.Graphics.DrawEllipse(pen, eventArgs.ItemBounds.SubItemBounds(0).BoundsImage)

        pen.Dispose()

    End Sub

DrawItemBackground event handler draws on the item background area:

C#

    void ListViewDrawItemBackground(object sender, BetterListViewDrawItemBackgroundEventArgs eventArgs)
    {
        Brush brush = new LinearGradientBrush(
            eventArgs.ItemBounds.BoundsInner,
            Color.FromArgb(64, Color.DarkSeaGreen),
            Color.Transparent,
            LinearGradientMode.ForwardDiagonal);

        // draw over the item's background in the inner area
        eventArgs.Graphics.FillRectangle(brush, eventArgs.ItemBounds.BoundsInner);

        brush.Dispose();
    }

Visual Basic

    Sub ListViewDrawItemBackground(ByVal sender As Object, ByVal eventArgs As BetterListViewDrawItemBackgroundEventArgs)

        Dim brush As Brush = New LinearGradientBrush(
            eventArgs.ItemBounds.BoundsInner,
            Color.FromArgb(64, Color.DarkSeaGreen),
            Color.Transparent,
            LinearGradientMode.ForwardDiagonal)

        ' draw over the item's background in the inner area
        eventArgs.Graphics.FillRectangle(brush, eventArgs.ItemBounds.BoundsInner)

        brush.Dispose()

    End Sub

Better ListView: Ultimate .NET ListView replacement control for WinForms (C#, VB.NET)
Download More Info