Back to Devexpress

Scrollbar Annotations

windowsforms-120556-controls-and-libraries-data-grid-scrolling-scrollbar-annotations.md

latest13.1 KB
Original Source

Scrollbar Annotations

  • May 31, 2025
  • 6 minutes to read

When grids contain many rows, locating those with validation errors, and those that are focused or selected, can be difficult. To help locate these rows expeditiously, display scrollbar annotations. The latter are colored marks on the vertical scrollbar that reflect the location of corresponding rows in the grid.

How to Enable

The GridView.OptionsScrollAnnotations property provides access to options that allow you to enable/disable specific annotations.

  • ShowErrors — specifies whether to mark rows with validation errors
  • ShowFocusedRow — specifies whether to mark the focused row
  • ShowSelectedRows — specifies whether to mark selected rows
  • ShowCustomAnnotations — specifies whether to mark rows with custom annotations provided using a dedicated event (see below)

Scrollbar annotations are disabled if a property equals to Default. Set the property to True to enable them.

csharp
// Enable annotations for the focused row.
gridView.OptionsScrollAnnotations.ShowFocusedRow = DefaultBoolean.True;
vb
' Enable annotations for the focused row.
gridView.OptionsScrollAnnotations.ShowFocusedRow = DefaultBoolean.True

The grid control also displays scrollbar annotations for search requests if the Find Panel is in search mode.

Limitations

Scrollbar annotations have the following limitations.

  • Lookup editors (see GridLookUpEdit, SearchLookUpEdit) do not support scrollbar annotations for search requests in the Find Panel.
  • Scrollbar annotations for validation errors and search requests are not supported in the Server Mode.
  • Scrollbar annotations for selected rows are only supported in the multiple row selection mode (see ColumnViewOptionsSelection.MultiSelect).
  • In Touch scroll mode, scroll bars are displayed in a separate window and may overlap other application’s windows. See the following topic for more information: ScrollUIMode.
  • Fluent scrollbars remain visible when annotations are enabled. The GridControl does not auto-hide them. See the following help topic for more information: WindowsFormsSettings.ScrollUIMode.

Custom Annotations

The GridView.CustomScrollAnnotation event allows you to specify custom annotations. The GridScrollAnnotationInfo type specifies data about custom annotations and exposes the following properties:

  • RowHandle — handle of the required row (see Row handles in the Rows topic)
  • Color — color of the mark on the scrollbar

When handling this event, explicitly initialize the e.Annotations collection, create data objects, and add them to the collection.

csharp
using using DevExpress.XtraGrid.Views.Grid;

void OnCustomScrollAnnotation(object sender, GridCustomScrollAnnotationsEventArgs e) {
    e.Annotations = new List<GridScrollAnnotationInfo>();
    GridScrollAnnotationInfo info = new GridScrollAnnotationInfo() { RowHandle = 74, Color = Color.Red };
    e.Annotations.Add(info);
}
vb
Imports using DevExpress.XtraGrid.Views.Grid

Private Sub OnCustomScrollAnnotation(ByVal sender As Object, ByVal e As GridCustomScrollAnnotationsEventArgs)
    e.Annotations = New List(Of GridScrollAnnotationInfo)()
    Dim info As New GridScrollAnnotationInfo() With {.RowHandle = 74, .Color = Color.Red}
    e.Annotations.Add(info)
End Sub

You can also use the e.SetAnnotations method to set annotations for a row array.

csharp
void OnCustomScrollAnnotation(object sender, GridCustomScrollAnnotationsEventArgs e) {
    int[] rowHandles = new int[] { 5, 17, 74 };
    e.SetAnnotations(Color.Red, rowHandles);
}
vb
Private Sub OnCustomScrollAnnotation(ByVal sender As Object, ByVal e As GridCustomScrollAnnotationsEventArgs) Handles gridView.CustomScrollAnnotation
    Dim rowHandles() As Integer = {5, 17, 74}
    e.SetAnnotations(Color.Red, rowHandles)
End Sub

Use the RefreshScrollAnnotations method to force the grid control to update/redraw scrollbar annotations.

How to: Create Row Bookmarks Using Scrollbar Annotations and Row Indicators

Note

Run the Scrollbar Annotations & Bookmarks module in the XtraGrid demo to see the functionality in action.

You can provide users with the ability to bookmark specific rows and navigate between them using the keyboard. To implement this functionality, handle the following events.

csharp
using DevExpress.XtraEditors.Annotations;
using DevExpress.XtraGrid.Views.Grid;
using DevExpress.XtraGrid.Views.Grid.Drawing;

gridView.CustomScrollAnnotation += OnCustomScrollAnnotation;
gridView.CustomDrawRowIndicator += OnCustomDrawRowIndicator;
gridView.ScrollAnnotationsStyle += OnScrollAnnotationsStyle;
gridView.KeyDown += OnKeyDown;

readonly HashSet<int> bookmarks = new HashSet<int>() { 5, 17, 74 };
// Set custom annotations.
void OnCustomScrollAnnotation(object sender, GridCustomScrollAnnotationsEventArgs e) {
    int[] rowHandles = bookmarks.Select(x => gridView.GetRowHandle(x)).ToArray();
    e.SetAnnotations(DevExpress.LookAndFeel.DXSkinColors.IconColors.Blue, rowHandles);
}
readonly AnnotationsStyle style = new AnnotationsStyle();
void OnScrollAnnotationsStyle(object sender, GridScrollAnnotationsStyleEventArgs e) {
    var styleColor = style.GetColor(e.Kind);
    if(!styleColor.IsEmpty)
        e.Color = styleColor;
}
// Draw a bookmark glyph.
void OnCustomDrawRowIndicator(object sender, RowIndicatorCustomDrawEventArgs e) {
    if(e.RowHandle >= 0) {
        if(e.Info.ImageIndex == GridPainter.IndicatorError ||
            e.Info.ImageIndex == GridPainter.IndicatorFocusedError) {
            e.Info.ImageIndex = (e.RowHandle == gridView.FocusedRowHandle) ? GridPainter.IndicatorFocused : -1;
        }
        if(!bookmarks.Contains(gridView.GetDataSourceRowIndex(e.RowHandle)))
            return;
        e.DefaultDraw();
        var bookmarkImage = svgImageCollection.GetImage("bookmark", GetPalette(), ScaleDPI.ScaleSize(new Size(8, 8)));
        var imageBounds = PlacementHelper.Arrange(bookmarkImage.Size, e.Bounds, ContentAlignment.MiddleLeft);
        e.Cache.DrawImageUnscaled(bookmarkImage, imageBounds);
        e.Handled = true;
    }
}
Utils.Design.ISvgPaletteProvider GetPalette() {
    return Utils.Svg.SvgPaletteHelper.GetSvgPalette(gridControl.LookAndFeel, Utils.Drawing.ObjectState.Normal);
}
// Implement forward and back navigation.
void OnKeyDown(object sender, KeyEventArgs e) {
    if(e.KeyData == (Keys.F2 | Keys.Control) || e.KeyData == (Keys.B | Keys.Control))
        e.Handled = ToggleBookmark(gridView.FocusedRowHandle);
    if(e.KeyData == Keys.F2)
        e.Handled = gridView.MoveToNextScrollAnnotation(ScrollAnnotationKind.Custom);
    if(e.KeyData == (Keys.F2 | Keys.Shift))
        e.Handled = gridView.MoveToPrevScrollAnnotation(ScrollAnnotationKind.Custom);
}
bool ToggleBookmark(int handle) {
    int dataIndex = gridView.GetDataSourceRowIndex(handle);
    if(dataIndex < 0)
        return false;
    if(bookmarks.Contains(dataIndex))
        bookmarks.Remove(dataIndex);
    else
        bookmarks.Add(dataIndex);
    gridView.RefreshScrollAnnotations(ScrollAnnotationKind.Custom);
    gridView.InvalidateRow(handle);
    return true;
}
vb
Imports DevExpress.XtraEditors.Annotations
Imports DevExpress.XtraGrid.Views.Grid
Imports DevExpress.XtraGrid.Views.Grid.Drawing

Private ReadOnly bookmarks As New HashSet(Of Integer)() From {5, 17, 74}
' Set custom annotations.
Private Sub OnCustomScrollAnnotation(ByVal sender As Object, ByVal e As GridCustomScrollAnnotationsEventArgs) Handles gridView.CustomScrollAnnotation
    Dim rowHandles() As Integer = bookmarks.Select(Function(x) gridView.GetRowHandle(x)).ToArray()
    e.SetAnnotations(DevExpress.LookAndFeel.DXSkinColors.IconColors.Blue, rowHandles)
End Sub
Private ReadOnly style As New AnnotationsStyle()
Private Sub OnScrollAnnotationsStyle(ByVal sender As Object, ByVal e As GridScrollAnnotationsStyleEventArgs) Handles gridView.ScrollAnnotationsStyle
    Dim styleColor = style.GetColor(e.Kind)
    If Not styleColor.IsEmpty Then
        e.Color = styleColor
    End If
End Sub
' Draw a bookmark glyph.
Private Sub OnCustomDrawRowIndicator(ByVal sender As Object, ByVal e As RowIndicatorCustomDrawEventArgs) Handles gridView.CustomDrawRowIndicator
    If e.RowHandle >= 0 Then
        If e.Info.ImageIndex = GridPainter.IndicatorError OrElse e.Info.ImageIndex = GridPainter.IndicatorFocusedError Then
            e.Info.ImageIndex = If((e.RowHandle = gridView.FocusedRowHandle), GridPainter.IndicatorFocused, -1)
        End If
        If (Not bookmarks.Contains(gridView.GetDataSourceRowIndex(e.RowHandle))) Then
            Return
        End If
        e.DefaultDraw()
        Dim bookmarkImage = svgImageCollection.GetImage("bookmark", GetPalette(), ScaleDPI.ScaleSize(New Size(8, 8)))
        Dim imageBounds = PlacementHelper.Arrange(bookmarkImage.Size, e.Bounds, ContentAlignment.MiddleLeft)
        e.Cache.DrawImageUnscaled(bookmarkImage, imageBounds)
        e.Handled = True
    End If
End Sub
Private Function GetPalette() As Utils.Design.ISvgPaletteProvider
    Return Utils.Svg.SvgPaletteHelper.GetSvgPalette(gridControl.LookAndFeel, Utils.Drawing.ObjectState.Normal)
End Function
' Implement forward and back navigation.
Private Sub OnGridKeyDown(ByVal sender As Object, ByVal e As KeyEventArgs) Handles gridView.KeyDown
    If e.KeyData = Keys.F2 Then
        e.Handled = gridView.MoveToNextScrollAnnotation(ScrollAnnotationKind.Custom)
    End If
    If e.KeyData = (Keys.F2 Or Keys.Shift) Then
        e.Handled = gridView.MoveToPrevScrollAnnotation(ScrollAnnotationKind.Custom)
    End If
    If e.KeyData = (Keys.F2 Or Keys.Control) OrElse e.KeyData = (Keys.B Or Keys.Control) Then
        e.Handled = ToggleBookmark(gridView.FocusedRowHandle)
    End If
End Sub
Private Function ToggleBookmark(ByVal handle As Integer) As Boolean
    Dim dataIndex As Integer = gridView.GetDataSourceRowIndex(handle)
    If dataIndex < 0 Then
        Return False
    End If
    If bookmarks.Contains(dataIndex) Then
        bookmarks.Remove(dataIndex)
    Else
        bookmarks.Add(dataIndex)
    End If
    gridView.RefreshScrollAnnotations(ScrollAnnotationKind.Custom)
    gridView.InvalidateRow(handle)
    Return True
End Function

See Also

Scrollbar Annotation Behavior

Tree List Scrollbar Annotations