This ListView has some extra features that a normal ListView doesn't have. First, you have add all the columns that you want to show. You provide the column name (from a datatable/dataview), the header text, the width (in pixels), and the cell alignment of the text (left, center, right). After that, you can LoadData, passing in a datatable or dataview, along with a start and ending index of the rows you want displayed (not providing any will default to show all rows). This will also automatically handle any and all sorting via a DataView. (If you sent in a datatable, I automatically put it into a dataview).

VB Code:
  1. Imports System.ComponentModel
  2. Imports System.Drawing
  3.  
  4. Public Class MKPPListView
  5.    Inherits System.Windows.Forms.ListView
  6.  
  7. #Region "<< Variables >>"
  8.    Private _columns As ArrayList
  9.    Private _captions As ArrayList
  10.    Private _widths As ArrayList
  11.    Private _dataSource As Object
  12.    Private _start As Int32
  13.    Private _finish As Int32
  14.    Private _contextMenu As ContextMenu
  15.    Private _helpText As String
  16.    Private _sorting As Boolean
  17. #End Region
  18.  
  19. #Region "<< Properties >>"
  20.    <Browsable(True), DefaultValue(True)> _
  21.    Public Property AllowSorting() As Boolean
  22.       Get
  23.          Return _sorting
  24.       End Get
  25.       Set(ByVal Value As Boolean)
  26.          _sorting = Value
  27.       End Set
  28.    End Property
  29.    <Browsable(True)> _
  30.    Public Property HelpText() As String
  31.       Get
  32.          Return _helpText
  33.       End Get
  34.       Set(ByVal Value As String)
  35.          _helpText = Value
  36.       End Set
  37.    End Property
  38.    <Browsable(False)> _
  39.    Public ReadOnly Property SelectedIndex() As Int32
  40.       Get
  41.          For i As Int32 = 0 To Me.Items.Count - 1
  42.             Dim row As ListViewItem = Me.Items(i)
  43.             If row.Selected = True Then
  44.                Return i
  45.             End If
  46.          Next
  47.          Return -1
  48.       End Get
  49.    End Property
  50.    Public Property RowFilter() As String
  51.       Get
  52.          If TypeOf _dataSource Is DataView Then
  53.             Return CType(_dataSource, DataView).RowFilter
  54.          End If
  55.       End Get
  56.       Set(ByVal Value As String)
  57.          If TypeOf _dataSource Is DataView Then
  58.             CType(_dataSource, DataView).RowFilter = Value
  59.          End If
  60.       End Set
  61.    End Property
  62.    Public Property SortData() As String
  63.       Get
  64.          If TypeOf _dataSource Is DataView Then
  65.             Return CType(_dataSource, DataView).Sort
  66.          End If
  67.       End Get
  68.       Set(ByVal Value As String)
  69.          If TypeOf _dataSource Is DataView Then
  70.             CType(_dataSource, DataView).Sort = Value
  71.             MyBase.Items.Clear()
  72.             SetupListView()
  73.          End If
  74.       End Set
  75.    End Property
  76.    Public ReadOnly Property Count() As Int32
  77.       Get
  78.          Return MyBase.Items.Count
  79.       End Get
  80.    End Property
  81. #End Region
  82.  
  83. #Region "<< Startup >>"
  84.    Public Sub New()
  85.       MyBase.New()
  86.       _columns = New ArrayList
  87.       _widths = New ArrayList
  88.       _captions = New ArrayList
  89.       MyBase.View = View.Details
  90.       MyBase.FullRowSelect = True
  91.       MyBase.MultiSelect = False
  92.       MyBase.ForeColor = Color.Yellow
  93.       MyBase.BackColor = Color.Black
  94.       MyBase.AllowColumnReorder = True
  95.       MyBase.Scrollable = True
  96.       _sorting = True
  97.       AddColumn("", "", 0, HorizontalAlignment.Center)
  98.       _contextMenu = New ContextMenu
  99.       Me.ContextMenu = _contextMenu
  100.       Me.ContextMenu.MenuItems.Add(New MenuItem("What's This?", AddressOf WhatsThis))
  101.    End Sub
  102. #End Region
  103.  
  104. #Region "<< Helper Methods >>"
  105.    Private Sub WhatsThis(ByVal sender As Object, ByVal e As EventArgs)
  106.       Help.ShowPopup(Me, HelpText, System.Windows.Forms.Form.MousePosition)
  107.    End Sub
  108. #End Region
  109.  
  110. #Region "<< Public Methods >>"
  111.    Public Sub SetCaption(ByVal index As Int32, ByVal newCaption As String)
  112.       _captions(index) = newCaption
  113.       Me.Columns(index).Text = newCaption
  114.    End Sub
  115.    Public Function SelectedItem(ByVal Column As String) As String
  116.       Dim i As Int32
  117.       For i = 0 To _columns.Count - 1
  118.          If CType(_columns(i), String) = Column Then
  119.             Return SelectedItem(i)
  120.          End If
  121.       Next
  122.       Throw New DataException(Column & " does not exist!")
  123.    End Function
  124.    Public Function SelectedItem(ByVal Column As Int32) As String
  125.       Dim selected As New ListView.SelectedListViewItemCollection(Me)
  126.       If selected.Count = 0 Then
  127.          Return Nothing
  128.       Else
  129.          Return selected.Item(0).SubItems(Column).Text
  130.       End If
  131.    End Function
  132.    Public Function SelectedItem() As ListViewItem
  133.       Dim selected As New ListView.SelectedListViewItemCollection(Me)
  134.       If selected.Count = 0 Then
  135.          Return Nothing
  136.       Else
  137.          Return selected.Item(0)
  138.       End If
  139.    End Function
  140.    Public Sub TypeFind(ByVal item As String, ByVal Column As String)
  141.       Dim i As Int32
  142.       For i = 0 To _columns.Count - 1
  143.          If CType(_columns(i), String) = Column Then
  144.             TypeFind(item, i)
  145.             Exit For
  146.          End If
  147.       Next
  148.    End Sub
  149.    Public Sub TypeFind(ByVal item As String, ByVal Column As Int32)
  150.       Dim i As Int32
  151.       For i = 0 To MyBase.Items.Count - 1
  152.          If MyBase.Items(i).SubItems(Column).Text.ToLower.StartsWith(item.ToLower) Then
  153.             MyBase.Items(i).EnsureVisible()
  154.             MyBase.Items(i).Selected = True
  155.             Exit For
  156.          End If
  157.       Next
  158.    End Sub
  159.    Public Sub SetAlternateRowColor(ByVal ForeColor As Color, ByVal BackColor As Color)
  160.       Dim i As Int32
  161.       For i = 0 To MyBase.Items.Count - 1
  162.          If i Mod 2 = 1 Then
  163.             MyBase.Items(i).BackColor = BackColor
  164.             MyBase.Items(i).ForeColor = ForeColor
  165.          End If
  166.       Next
  167.    End Sub
  168. #End Region
  169.  
  170. #Region "<< Add Column >>"
  171.    Public Sub AddColumn(ByVal Column As String, ByVal Caption As String)
  172.       AddColumn(Column, Caption, 0)
  173.    End Sub
  174.    Public Sub AddColumn(ByVal Column As String, ByVal Caption As String, ByVal Width As Int32)
  175.       AddColumn(Column, Caption, Width, HorizontalAlignment.Left)
  176.    End Sub
  177.    Public Sub AddColumn(ByVal Column As String, ByVal Caption As String, ByVal Alignment As HorizontalAlignment)
  178.       AddColumn(Column, Caption, 0, Alignment)
  179.    End Sub
  180.    Public Sub AddColumn(ByVal Column As String, ByVal Caption As String, ByVal Width As Int32, ByVal Alignment As HorizontalAlignment)
  181.       _columns.Add(Column)
  182.       _captions.Add(Caption)
  183.       _widths.Add(Width)
  184.       MyBase.Columns.Add(Caption, Width, Alignment)
  185.    End Sub
  186. #End Region
  187.  
  188. #Region "<< Load Data >>"
  189.    Public Sub LoadData(ByRef Data As DataTable)
  190.       LoadData(Data, 0, Data.Rows.Count - 1)
  191.    End Sub
  192.    Public Sub LoadData(ByRef Data As DataView)
  193.       LoadData(Data, 0, Data.Count - 1)
  194.    End Sub
  195.    Public Sub LoadData(ByRef Data As DataTable, ByVal Start As Int32, ByVal Finish As Int32)
  196.       LoadData(New DataView(Data), Start, Finish)
  197.    End Sub
  198.    Public Sub LoadData(ByRef Data As DataView, ByVal Start As Int32, ByVal Finish As Int32)
  199.       MyBase.Items.Clear()
  200.       _dataSource = Data
  201.       _start = Start
  202.       _finish = Finish
  203.       SetupListView()
  204.    End Sub
  205. #End Region
  206.  
  207. #Region "<< SetupListView >>"
  208.    Private Sub SetupListView()
  209.       Dim i As Int32, j As Int32
  210.       If TypeOf _dataSource Is DataTable Then
  211.          With CType(_dataSource, DataTable)
  212.             For i = _start To _finish
  213.                Dim item As New ListViewItem(.Rows(i)(CType(_columns(1), Int32)).ToString)
  214.                For j = 1 To _columns.Count - 1
  215.                   item.SubItems.Add(.Rows(i)(CType(_columns(j), Int32)).ToString)
  216.                Next
  217.                MyBase.Items.Add(item)
  218.             Next
  219.          End With
  220.       ElseIf TypeOf _dataSource Is DataView Then
  221.          With CType(_dataSource, DataView)
  222.             For i = _start To _finish
  223.                Dim item As New ListViewItem(.Item(i)(CType(_columns(1), String)).ToString)
  224.                For j = 1 To _columns.Count - 1
  225.                   item.SubItems.Add(.Item(i)(CType(_columns(j), String)).ToString)
  226.                Next
  227.                MyBase.Items.Add(item)
  228.             Next
  229.          End With
  230.       End If
  231.       If MyBase.Columns(1).Width = 0 Then
  232.          Dim gr As Graphics = MyBase.CreateGraphics
  233.          For i = 1 To _columns.Count - 1
  234.             Dim width As Int32 = CType(gr.MeasureString(MyBase.Columns(i).Text, Me.Font).Width, Int32)
  235.             width += 5
  236.             For j = 0 To MyBase.Items.Count - 1
  237.                Dim myWidth As Int32 = CType(gr.MeasureString(MyBase.Items(j).SubItems(i).Text, MyBase.Font).Width, Int32)
  238.                If i > 1 Then
  239.                   myWidth += 5
  240.                End If
  241.                If myWidth > width Then
  242.                   width = myWidth
  243.                End If
  244.             Next
  245.             MyBase.Columns(i).Width = width
  246.             width = 0
  247.          Next
  248.       End If
  249.    End Sub
  250. #End Region
  251.  
  252. #Region "<< Column Sorting >>"
  253.    Private Sub MKPPListView_ColumnClick(ByVal sender As Object, ByVal e As System.Windows.Forms.ColumnClickEventArgs) Handles MyBase.ColumnClick
  254.       If AllowSorting Then
  255.          If TypeOf _dataSource Is DataView Then
  256.             Dim col As String = MyBase.Columns(e.Column).Text
  257.             Dim i As Int32
  258.             For i = 0 To _captions.Count - 1
  259.                If CType(_captions(i), String) = col Then
  260.                   col = CType(_columns(i), String)
  261.                   Exit For
  262.                End If
  263.             Next
  264.             If CType(_dataSource, DataView).Sort = col Then
  265.                CType(_dataSource, DataView).Sort = col & " DESC"
  266.             Else
  267.                CType(_dataSource, DataView).Sort = col
  268.             End If
  269.             MyBase.Items.Clear()
  270.             SetupListView()
  271.          End If
  272.       End If
  273.    End Sub
  274. #End Region
  275.  
  276. End Class