« Multi-line Items | Index | Performance » |
Owner drawing allow to customize appearance of any element, element part and the control itself:
The simple way to draw over control parts is by using drawing events:
DrawBackground
DrawColumnHeader
DrawColumnHeaderBackground
DrawGroup
DrawGroupBackground
DrawItem
DrawItemBackground
DrawInsertionMark
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.
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
OnDrawInsertionMark
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
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:
Draw item as if the control is in enabled state (BetterListView.Enabled is true).
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).
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
« Multi-line Items | Index | Performance » |
Better ListView Documentation | Copyright © 2010-2012 ComponentOwl.com |