Insertion Mark



Better ListView Express does not support groups or hierarchical items, so the insertion mark can be placed on items only in the Express edition.



Insertion mark is a line showing location between items. Better ListView support displaying the insertion mark on various locations with support for groups and item hierarchy:

The basic usage of insertion mark is the same as in regular .NET ListView. Setting InsertionMark property using one of these constructors will give you the classic insertion mark:

The last constructor has an extra parameter enabled which adjusts insertion mark color slightly (giving it alpha transparency) to be displayed in an inactive or disabled state.

There are also more general constructors for displaying insertion mark on arbitrary location in item hierarchy and on groups:

Instead of index, there is an insertionLocation parameter.

Insertion Locations

The BetterListViewInsertionLocation type can describe any location in item hierarchy and on groups. The location consists of three properties:

Address is a counterpart of index in item hierarchy (see Addressing Elements). It can describe either group or a child item.

DropPart defines relative insertion location to the element specified by the Address. The drop part value can be either Before the element, After the element or Inside the element. For groups, the Inside is the only valid value. Items can display any of the three drop parts. The difference between After and Inside is that with Inside it is possible to create new child items. Otherwise, the location inside item can be substituted by before first child item of that item.

Level specifies target level in item hierarchy. It is valid for Before and After drop parts only. By default, the Level property has value of BetterListViewInsertionLocation.LevelUndefined and thus inheriting level of the currently located item. When set, it overrides the level and the insertion mark can start on smaller offset than the child item. This is used mainly internally for item reordering, when user puts item after the last child item and then moves mouse cursor to the left, to put it after its parent, actually.

Sample Source Code

The following sample shows how to display insertion mark according to current mouse position (see Hit Test).

C#

this.listView.BeginUpdate();

// create groups with items and child items
BetterListViewGroup groupRecent = new BetterListViewGroup("Recent Items");

groupRecent.Items.AddRange(
    new[]
    {
        "Ming Dynasty Vase",
        "Collection of Rembrandt",
        "Photos from Prokudin Gorskij"
    });

groupRecent.Items[1].ChildItems.AddRange(
    new[]
    {
        "The Night Watch",
        "Belshazzar's Feast"
    });

BetterListViewGroup groupArchived = new BetterListViewGroup("Archived Items");

groupArchived.Items.AddRange(
    new[]
    {
        "Statue of Zeus",
        "Rare pens from Hamburg and Dresden"
    });

this.listView.Groups.AddRange(
    new[]
    {
        groupRecent,
        groupArchived
    });

// set custom color for the insertion mark
this.listView.ColorInsertionMark = Color.DarkGreen;
// make the groups visible
this.listView.ShowGroups = true;

this.listView.EndUpdate();

// this will set insertion mark every time hit test changes
this.listView.HitTestChanged += ListViewHitTestChanged;

Visual Basic

ListView.BeginUpdate()

' create groups with items and child items
Dim groupRecent As New BetterListViewGroup("Recent Items")

groupRecent.Items.AddRange(
    New String() {
        "Ming Dynasty Vase",
        "Collection of Rembrandt",
        "Photos from Prokudin Gorskij"
                 })

groupRecent.Items(1).ChildItems.AddRange(
    New String() {
        "The Night Watch",
        "Belshazzar's Feast"
                 })

Dim groupArchived As New BetterListViewGroup("Archived Items")

groupArchived.Items.AddRange(
    New String() {
        "Statue of Zeus",
        "Rare pens from Hamburg and Dresden"
                 })

ListView.Groups.AddRange(New BetterListViewGroup() {groupRecent, groupArchived})

' set custom color for the insertion mark
ListView.ColorInsertionMark = Color.DarkGreen
' make the groups visible
ListView.ShowGroups = True

ListView.EndUpdate()

' this will set insertion mark every time hit test changes
AddHandler ListView.HitTestChanged, AddressOf ListViewHitTestChanged

The HitTestInfoChanged event handler determines the actual insertion mark location and sets it:

C#

void ListViewHitTestChanged(object sender, BetterListViewHitTestChangedEventArgs eventArgs)
{
    // get current hit test information
    BetterListViewHitTestInfo hitTestInfo = eventArgs.HitTestInfoNew;

    // get address and drop part to assembly an insertion mark location
    BetterListViewAddress address;
    BetterListViewDropPart dropPart;

    if (hitTestInfo.Item != null)
    {
        // the mouse cursor is located on item
        address = hitTestInfo.Item.Address;

        if ((hitTestInfo.ItemPart & BetterListViewHitPart.VCenter) == BetterListViewHitPart.VCenter)
        {
            // the mouse cursor is located in the centre of the item - the insertion mark will point inside the item
            dropPart = BetterListViewDropPart.Inside;
        }
        else
        {
            // the mouse cursor is located on other parts of the item - the insertion mark will point before on after the item
            dropPart = (((hitTestInfo.ItemPart & BetterListViewHitPart.Bottom) == BetterListViewHitPart.Bottom)
                            ? BetterListViewDropPart.After
                            : BetterListViewDropPart.Before);
        }
    }
    else if (
        hitTestInfo.Group != null)
    {
        // the mouse cursor is located on group
        address = hitTestInfo.Group.Address;
        dropPart = BetterListViewDropPart.Inside; //NOTE: only Inside is allowed as drop part on groups
    }
    else
    {
        // the mouse cursor is not located on item nor group
        address = null;
        dropPart = BetterListViewDropPart.Undefined;
    }

    if (address != null)
    {
        // set insertion mark on the constructed location
        this.listView.InsertionMark = new BetterListViewInsertionMark(new BetterListViewInsertionLocation(address, dropPart));
    }
    else
    {
        // reset insertion mark
        this.listView.InsertionMark = BetterListViewInsertionMark.Empty;
    }
}

Visual Basic

Sub ListViewHitTestChanged(ByVal sender As Object, ByVal eventArgs As BetterListViewHitTestChangedEventArgs)

    ' get current hit test information
    Dim hitTestInfo As BetterListViewHitTestInfo = eventArgs.HitTestInfoNew

    ' get address and drop part to assembly an insertion mark location
    Dim address As BetterListViewAddress
    Dim dropPart As BetterListViewDropPart

    If hitTestInfo.Item IsNot Nothing Then

        ' the mouse cursor is located on item
        address = hitTestInfo.Item.Address

        If (hitTestInfo.ItemPart And BetterListViewHitPart.VCenter) = BetterListViewHitPart.VCenter Then

            ' the mouse cursor is located in the centre of the item - the insertion mark will point inside the item
            dropPart = BetterListViewDropPart.Inside

        Else

            ' the mouse cursor is located on other parts of the item - the insertion mark will point before on after the item
            dropPart = (If(((hitTestInfo.ItemPart And BetterListViewHitPart.Bottom) = BetterListViewHitPart.Bottom), BetterListViewDropPart.After, BetterListViewDropPart.Before))

        End If

    ElseIf hitTestInfo.Group IsNot Nothing Then

        ' the mouse cursor is located on group
        address = hitTestInfo.Group.Address
        'NOTE: only Inside is allowed as drop part on groups
        dropPart = BetterListViewDropPart.Inside

    Else

        ' the mouse cursor is not located on item nor group
        address = Nothing
        dropPart = BetterListViewDropPart.Undefined

    End If

    If address IsNot Nothing Then

        ' set insertion mark on the constructed location
        ListView.InsertionMark = New BetterListViewInsertionMark(New BetterListViewInsertionLocation(address, dropPart))

    Else

        ' reset insertion mark
        ListView.InsertionMark = BetterListViewInsertionMark.Empty

    End If

End Sub