Click here to Skip to main content
15,886,258 members
Articles / Programming Languages / Visual Basic

ReorderListView Control with AutoScroll

Rate me:
Please Sign up or sign in to vote.
4.50/5 (2 votes)
3 Mar 2009CPOL4 min read 27.5K   826   16  
A VB version plus enhancements to "Manual reordering of items inside a ListView".

Introduction

This control is an extension of the code in the article entitled "Manual reordering of items inside a ListView" by mav.northwind. Mav gets the credit. I simply needed a few more features, so I put them in, and am posting this for those who may benefit. Additionally, I adapted the auto-scrolling features discussed by Les Smith in his article ListView Drag & Drop With Auto Scrolling in .NET (Upgraded).

The following features were added to the control developed by mav.northwind:

  • Multi-select item reordering functionality
  • Auto-scroll the ListView while reordering
  • Enable/Disable reordering functionality with the DisableItemReorder property
  • Ability to lock the first (n) items in the list with the ReorderStartIndex property
  • Change the color of the insertion bar with the InsertionLineColor property

Additionally, I moved the ListView event handlers for reordering into the ListView control itself so there is no need to handle anything within the form. Finally, since my project needed to be done in VB, I changed the code from C# for all you VB programmers.

Background

For background on the ideas in this article, you should consult the article by mav.northwind, Manual reordering of items inside a ListView. There are other solutions on how to do this, typically using the drag/drop events. I liked this method as it is clean and leaves the drag/drop free for handling drag/drop from external items. I also recommend Les Smith's article, ListView Drag & Drop With Auto Scrolling in .NET (Upgraded) dealing with the same topic, but addressing the auto-scroll functionality as well.

Using the Code

To use this code, simply add the custom control class ReorderListView to your project. Build the control class, then use the ReorderListView control on a windows Form. The sample code and project are done in VS2008; however, the code should work fine in earlier versions.

Points of Interest

Support for handling multiple selected items is done simply by first storing the selected items into a list collection, then removing them from the ListView, and finally, inserting them all back into the ListView at the proper index. As for auto-scrolling, it is simply a matter of using the SendMessageA function to scroll the control. A timer was added and the onTick event handled to initiate the SendMessage routine, thus the timer Interval sets the frequency with which the SendMessage routine is called. This results in more frequent SendMessage calls when the timer Interval value is small, hence faster scrolling, and fewer calls when the timer Interval is greater for slower scrolling.

VB
Public Sub New()

    ' This call is required by the Windows Form Designer.
    InitializeComponent()

    'Reduce Flicker
    SetStyle(Windows.Forms.ControlStyles.OptimizedDoubleBuffer, True)

    'Initialize Scrolling Timer
    tmrLVScroll.Enabled = False
    tmrLVScroll.Interval = 100

End Sub


#Region "Scrolling Support"
   'This section handles the auto-scrolling when an item 
  'is dragged to the top or bottom of the list

  Private Declare Function SendMessage Lib "user32" _
          Alias "SendMessageA" (ByVal hwnd As Integer, _
          ByVal wMsg As Integer, ByVal wParam As Integer, _
          ByRef lParam As Object) As Integer

  Private Sub tmrLVScroll_Tick(ByVal sender As System.Object, _
          ByVal e As System.EventArgs) Handles tmrLVScroll.Tick
    ScrollControl(Me, intScrollDirection)
  End Sub

  Private Sub ScrollControl(ByRef objControl As Control, ByRef intDirection As Integer)
    Const WM_SCROLL As Integer = &H115S
    SendMessage(objControl.Handle.ToInt32, WM_SCROLL, intDirection, VariantType.Null)
  End Sub

#End Region

Now, it's just a matter of enabling the timer to scroll and ascertaining the direction of scroll, and disabling it when not scrolling. To enable/disable the timer at the right time, I added a small bit of code in the MouseMove event shown below. I used the top item in the list rather than the top of the control itself to determine when the control should scroll up so that the scrolling works whether the column headers are displayed or not.

VB
'Scroll the listview when close to the top or bottom
Dim HeaderOffset As Integer
If Me.View = Windows.Forms.View.Details Then
    HeaderOffset = Me.TopItem.GetBounds(ItemBoundsPortion.Entire).Top

If e.Y <= HeaderOffset + Me.Font.Height / 1.5 Then
  intScrollDirection = 0
  tmrLVScroll.Enabled = True
ElseIf e.Y >= Me.ClientSize.Height - Me.Font.Height / 1.5 Then
  intScrollDirection = 1
  tmrLVScroll.Enabled = True
Else
  tmrLVScroll.Enabled = False
End If

This was quite a simple implementation, so there's no real mystery here. No fancy coding, everything is pretty straightforward, but that's what I prefer as there's fewer "undocumented features". I should also point out that items do get reordered as far as their index values are concerned in any view (Large Icon, List, Details, etc.); however, the items are not redrawn correctly in the ListView for views other than list and details, so they don't appear to have changed until the view is changed, then changed back, (or maybe if all the items are re-loaded). Since I only needed the details view anyway, I didn't bother to pursue that, but if you want to reorder items in the Large Icon view, this is a good place to start. I did correct the way the insertion bar displays for those other views from the original article. Thanks to mav.northwind for the original post. I hope this can help someone out.

Due to time constraints, I don't plan to support this, so I don't expect to post new updates. Use it as is - but if you do have a suggestion for fixing the display update after reordering in Large Icon and other views, I'm sure someone would like to hear about it. Thanks to all!

History

  • March 3, 2009 - Initial post.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
-- There are no messages in this forum --