HOWTO: Sorting a list view in detail mode in .NET 2.0 while in virtual mode

B

Brian Henry

Here is another virtual mode example for the .NET 2.0 framework while
working with the list view. Since you can not access the items collection of
the list view you need to do sorting another way... here is my code on how I
did it to help anyone starting out get an idea of how to use virtual mode in
..NET 2.0

Imports CrystalDecisions.CrystalReports.Engine

Imports CrystalDecisions.Shared

Public Class Form1

''' <summary>

''' Retrieve thousands of rows of data from database server to fill dataset
to populate list view

''' </summary>

''' <remarks></remarks>

Dim aItems(0) As ListViewItem

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load

' fill data then process it into an array

da.Fill(ds, "entries")

LoadData()

End Sub





''' <summary>

''' Moves data from data set into an array of list view items (speeds things
up when you preprocess the

''' data set into list view items so you dont have to make them on the fly
when retrieveing virtual items

''' </summary>

''' <remarks></remarks>

Private Sub LoadData()

Me.ListView1.VirtualListSize = 0

If Not aItems Is Nothing Then

Array.Clear(aItems, 0, aItems.Length)

End If

Array.Resize(aItems, ds.Tables("entries").Rows.Count)

Dim i As Integer = 0

for each dr as datarow in ds.tables("entries").rows

dim lvitem as listviewitem

' pre process list view items now the add them to the array here

aItems(i) = lvItem

i += 1

Application.DoEvents()

Next

Me.ListView1.VirtualMode = True

Me.ListView1.VirtualListSize = aItems.Length



End Sub

''' <summary>

''' This is the column clicked event of the list view

''' you need to sort the array that contains the list view items

''' when ever this happens based on the column that was clicked on

''' after this, the array will be sorted, but the list view will not

''' reflect this change. Because of this, you must invalidate the

''' list view to force it to reflect the change of the array that was

''' sorted on screen

''' </summary>

''' <param name="sender"></param>

''' <param name="e"></param>

''' <remarks>Must invalidate list view after sorting to force on screen
changes</remarks>

Private Sub ListView1_ColumnClick(ByVal sender As Object, ByVal e As
System.Windows.Forms.ColumnClickEventArgs) Handles ListView1.ColumnClick

Debug.WriteLine("Column header clicked")

If Me.ListView1.Sorting = SortOrder.Ascending Then

Me.ListView1.Sorting = SortOrder.Descending

Else

Me.ListView1.Sorting = SortOrder.Ascending

End If

Dim sorter As New ListViewSortOrder(e.Column, Me.ListView1.Sorting)

Array.Sort(aItems, sorter)

Me.ListView1.Invalidate()

End Sub

Private Sub ListView1_DrawColumnHeader(ByVal sender As Object, ByVal e As
System.Windows.Forms.DrawListViewColumnHeaderEventArgs) Handles
ListView1.DrawColumnHeader

e.DrawDefault = True

End Sub



''' <summary>

''' Sort comparision class which implements IComparable

''' This will be used to sort the array of list view items

''' that the virtual mode list view uses to display

''' </summary>

''' <remarks></remarks>

Private Class ListViewSortOrder

Implements IComparer

Dim column As Integer

Dim order As SortOrder = SortOrder.Ascending

Public Sub New(ByVal aColumn As Integer, ByVal aorder As SortOrder)

column = aColumn

order = aorder

End Sub

Public Function Compare(ByVal x As Object, ByVal y As Object) As Integer
Implements System.Collections.IComparer.Compare

Dim xItem, yItem As System.Windows.Forms.ListViewItem

xItem = CType(x, ListViewItem)

yItem = CType(y, ListViewItem)

If order = SortOrder.Ascending Then

Return (xItem.SubItems(column).Text).CompareTo(yItem.SubItems(column).Text)

Else

Return (yItem.SubItems(column).Text).CompareTo(xItem.SubItems(column).Text)

End If

End Function

End Class

''' <summary>

''' Pulls the virtual item out of the list as it is needed to display on the
screen from the

''' array of preprocessed list view items from the initially loaded data set

''' </summary>

''' <param name="sender"></param>

''' <param name="e"></param>

''' <remarks></remarks>

Private Sub ListView1_RetrieveVirtualItem(ByVal sender As Object, ByVal e As
System.Windows.Forms.RetrieveVirtualItemEventArgs) Handles
ListView1.RetrieveVirtualItem

e.Item = aItems(e.ItemIndex)

End Sub



''' <summary>

''' This happens when a selection is reset to no items selected, like when a
user clicks off a selection

''' </summary>

''' <param name="sender"></param>

''' <param name="e"></param>

''' <remarks></remarks>

Private Sub ListView1_VirtualItemsSelectionRangeChanged(ByVal sender As
Object, ByVal e As
System.Windows.Forms.ListViewVirtualItemsSelectionRangeChangedEventArgs)
Handles ListView1.VirtualItemsSelectionRangeChanged

Me.ListBox1.BeginUpdate()

Debug.WriteLine(String.Format("{3}: Start {0}, End {1}, IsSelected {2}",
e.StartIndex, e.EndIndex, e.IsSelected, Now.ToLongTimeString))

Me.ListBox1.Items.Clear()

Me.ListBox1.EndUpdate()

End Sub

''' <summary>

''' This happens when a user selects items or multiple selects items or
deselects one of the multi selected items

''' This does not fire though if you have an item selected then click off it
or have multiple items selected then

''' click off them... the virutal selection range change happens at that
point and need to reset your selected

''' items list at that point

''' </summary>

''' <param name="sender"></param>

''' <param name="e"></param>

''' <remarks></remarks>

Private Sub ListView1_ItemSelectionChanged(ByVal sender As Object, ByVal e
As System.Windows.Forms.ListViewItemSelectionChangedEventArgs) Handles
ListView1.ItemSelectionChanged

Me.ListBox1.BeginUpdate()

Debug.WriteLine(String.Format("Item Changed: {0}, Is selected: {1}",
e.ItemIndex, e.IsSelected))

If e.IsSelected = True Then

Me.ListBox1.Items.Add(CStr(e.ItemIndex))

Else

Me.ListBox1.Items.Remove(CStr(e.ItemIndex))

End If

Me.ListBox1.EndUpdate()

End Sub

End Class





'======================================

Form designer partial class for control setup on form

' =========================================





<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _

Partial Class Form1

Inherits System.Windows.Forms.Form

'Form overrides dispose to clean up the component list.

<System.Diagnostics.DebuggerNonUserCode()> _

Protected Overrides Sub Dispose(ByVal disposing As Boolean)

If disposing AndAlso components IsNot Nothing Then

components.Dispose()

End If

MyBase.Dispose(disposing)

End Sub

'Required by the Windows Form Designer

Private components As System.ComponentModel.IContainer

'NOTE: The following procedure is required by the Windows Form Designer

'It can be modified using the Windows Form Designer.

'Do not modify it using the code editor.

<System.Diagnostics.DebuggerStepThrough()> _

Private Sub InitializeComponent()

Me.components = New System.ComponentModel.Container

Dim resources As System.ComponentModel.ComponentResourceManager = New
System.ComponentModel.ComponentResourceManager(GetType(Form1))

Me.ImageList1 = New System.Windows.Forms.ImageList(Me.components)

Me.ListBox1 = New System.Windows.Forms.ListBox

Me.ListView1 = New WindowsApplication9.DoubleBufferedListView

Me.clmTypeIcon = New System.Windows.Forms.ColumnHeader

Me.clmStatusIcon = New System.Windows.Forms.ColumnHeader

Me.clmAttachmentIcon = New System.Windows.Forms.ColumnHeader

Me.clmJournalType = New System.Windows.Forms.ColumnHeader

Me.clmEntryType = New System.Windows.Forms.ColumnHeader

Me.clmCreatedBy = New System.Windows.Forms.ColumnHeader

Me.clmDateCreated = New System.Windows.Forms.ColumnHeader

Me.clmAccount = New System.Windows.Forms.ColumnHeader

Me.clmEntryMessage = New System.Windows.Forms.ColumnHeader

Me.clmStatus = New System.Windows.Forms.ColumnHeader

Me.clmDueDate = New System.Windows.Forms.ColumnHeader

Me.clmEnrollee = New System.Windows.Forms.ColumnHeader

Me.SuspendLayout()

'

'ImageList1

'

Me.ImageList1.ImageStream =
CType(resources.GetObject("ImageList1.ImageStream"),
System.Windows.Forms.ImageListStreamer)

Me.ImageList1.TransparentColor = System.Drawing.Color.Transparent

Me.ImageList1.Images.SetKeyName(0, "EMAILhighimportance.png")

Me.ImageList1.Images.SetKeyName(1, "EMAILlowimportance.png")

Me.ImageList1.Images.SetKeyName(2, "bookclosedpurple.png")

Me.ImageList1.Images.SetKeyName(3, "bookopengreen.png")

Me.ImageList1.Images.SetKeyName(4, "bookopenred.png")

Me.ImageList1.Images.SetKeyName(5, "bookopenyellow.png")

'

'ListBox1

'

Me.ListBox1.FormattingEnabled = True

Me.ListBox1.Location = New System.Drawing.Point(0, 307)

Me.ListBox1.Name = "ListBox1"

Me.ListBox1.Size = New System.Drawing.Size(265, 225)

Me.ListBox1.TabIndex = 1

'

'ListView1

'

Me.ListView1.Columns.AddRange(New System.Windows.Forms.ColumnHeader()
{Me.clmTypeIcon, Me.clmStatusIcon, Me.clmAttachmentIcon, Me.clmJournalType,
Me.clmEntryType, Me.clmCreatedBy, Me.clmDateCreated, Me.clmAccount,
Me.clmEntryMessage, Me.clmStatus, Me.clmDueDate, Me.clmEnrollee})

Me.ListView1.Dock = System.Windows.Forms.DockStyle.Top

Me.ListView1.FullRowSelect = True

Me.ListView1.HideSelection = False

Me.ListView1.Location = New System.Drawing.Point(0, 0)

Me.ListView1.Name = "ListView1"

Me.ListView1.Size = New System.Drawing.Size(929, 301)

Me.ListView1.SmallImageList = Me.ImageList1

Me.ListView1.Sorting = System.Windows.Forms.SortOrder.Ascending

Me.ListView1.TabIndex = 0

Me.ListView1.UseCompatibleStateImageBehavior = False

Me.ListView1.View = System.Windows.Forms.View.Details

'

'clmTypeIcon

'

Me.clmTypeIcon.Name = "clmTypeIcon"

Me.clmTypeIcon.Width = 21

'

'clmStatusIcon

'

Me.clmStatusIcon.Name = "clmStatusIcon"

Me.clmStatusIcon.Width = 21

'

'clmAttachmentIcon

'

Me.clmAttachmentIcon.Name = "clmAttachmentIcon"

Me.clmAttachmentIcon.Width = 21

'

'clmJournalType

'

Me.clmJournalType.Name = "clmJournalType"

'

'clmEntryType

'

Me.clmEntryType.Name = "clmEntryType"

'

'clmCreatedBy

'

Me.clmCreatedBy.Name = "clmCreatedBy"

'

'clmDateCreated

'

Me.clmDateCreated.Name = "clmDateCreated"

'

'clmAccount

'

Me.clmAccount.Name = "clmAccount"

'

'clmEntryMessage

'

Me.clmEntryMessage.Name = "clmEntryMessage"

Me.clmEntryMessage.Width = 300

'

'clmStatus

'

Me.clmStatus.Name = "clmStatus"

'

'clmDueDate

'

Me.clmDueDate.Name = "clmDueDate"

'

'clmEnrollee

'

Me.clmEnrollee.Name = "clmEnrollee"

'

'Form1

'

Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)

Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font

Me.ClientSize = New System.Drawing.Size(929, 533)

Me.Controls.Add(Me.ListBox1)

Me.Controls.Add(Me.ListView1)

Me.Name = "Form1"

Me.Text = "Form1"

Me.ResumeLayout(False)

End Sub

Friend WithEvents ListView1 As DoubleBufferedListView

Friend WithEvents clmIconA As System.Windows.Forms.ColumnHeader

Friend WithEvents clmIconB As System.Windows.Forms.ColumnHeader

Friend WithEvents clmAttachments As System.Windows.Forms.ColumnHeader

Friend WithEvents clmJournalType As System.Windows.Forms.ColumnHeader

Friend WithEvents clmType As System.Windows.Forms.ColumnHeader

Friend WithEvents clmUser As System.Windows.Forms.ColumnHeader

Friend WithEvents clmDate As System.Windows.Forms.ColumnHeader

Friend WithEvents clmAccount As System.Windows.Forms.ColumnHeader

Friend WithEvents clmMessage As System.Windows.Forms.ColumnHeader

Friend WithEvents clmStatus As System.Windows.Forms.ColumnHeader

Friend WithEvents clmDueDate As System.Windows.Forms.ColumnHeader

Friend WithEvents clmEnrollee As System.Windows.Forms.ColumnHeader

Friend WithEvents clmTypeIcon As System.Windows.Forms.ColumnHeader

Friend WithEvents clmStatusIcon As System.Windows.Forms.ColumnHeader

Friend WithEvents clmAttachmentIcon As System.Windows.Forms.ColumnHeader

Friend WithEvents clmEntryType As System.Windows.Forms.ColumnHeader

Friend WithEvents clmCreatedBy As System.Windows.Forms.ColumnHeader

Friend WithEvents clmDateCreated As System.Windows.Forms.ColumnHeader

Friend WithEvents clmEntryMessage As System.Windows.Forms.ColumnHeader

Friend WithEvents ImageList1 As System.Windows.Forms.ImageList

Friend WithEvents ListBox1 As System.Windows.Forms.ListBox

End Class
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top