Как организовать сортировку в ListView, чтобы порядок сортировки был вида:
1,2,3,4,10,20,100,1000 и т.д.
А то стандартыми методами удается отсортировать так:
1,10,100,1000,2,20,3,4.
Public Function FastFMT(Expression As Double, _
LeadDigits As Byte) As String
On Error Resume Next
Dim strTmp As String
Dim lngTmp As Long
If LeadDigits = 1 Then _
FastFMT = CStr(Expression): Exit Function
lngTmp = 10 ^ (LeadDigits - 1)
If Expression >= lngTmp Then _
FastFMT = CStr(Expression): Exit Function
FastFMT = String(LeadDigits - _
Len(CStr(Expression)), "0") & CStr(Expression)
End Function
Oldman писал(а):Огромное спасибо за пример... Все более менее понятно, но как быстро данный алгоритм сортировки будет с таблицей примерно в 18-20 тыс. записей?
using System;
using System.Collections;
namespace DataGegevens
{
/// <summary>
/// Summary description for clData.
/// </summary>
///
public struct gegevens
{
public int nr;
public long volgnr;
public string naam;
public string voornaam;
public DateTime gebdat;
}
public class VglNr: IComparer
{
int IComparer.Compare(object var1, object var2)
{
if(var2.GetType()== typeof(gegevens))
return ((gegevens)var1).nr-((gegevens)var2).nr;
else
return ((gegevens)var1).nr-(int)var2;
}
}
public class VglNaam: IComparer
{
int IComparer.Compare(object var1, object var2)
{
if(var2.GetType()== typeof(gegevens))
return string.Compare(((gegevens)var1).naam,((gegevens)var2).naam);
else
return string.Compare(((gegevens)var1).naam,(string)var2);
}
}
public class VglVoorNaam: IComparer
{
int IComparer.Compare(object var1, object var2)
{
if(var2.GetType()== typeof(gegevens))
return string.Compare(((gegevens)var1).voornaam,((gegevens)var2).voornaam);
else
return string.Compare(((gegevens)var1).voornaam,(string)var2);
}
}
public class VglGebDat: IComparer
{
int IComparer.Compare(object var1, object var2)
{
if(var2.GetType()== typeof(gegevens))
return DateTime.Compare(((gegevens)var1).gebdat,((gegevens)var2).gebdat);
else
return DateTime.Compare(((gegevens)var1).gebdat,(DateTime)var2);
}
}
public class VglVolgNr: IComparer
{
int IComparer.Compare(object var1, object var2)
{
if(var2.GetType()== typeof(gegevens))
return (int)(((gegevens)var1).volgnr-((gegevens)var2).volgnr);
else
return (int)(((gegevens)var1).nr-(long)var2);
}
}
}
private void bttnSorteer_Click(object sender, System.EventArgs e)
{
dataTabel.Sort(myVgl);
tonen();
}
switch(kol)
{
case 0:
myVgl= new VglNr();
break;
case 1:
myVgl=new VglVolgNr();
break;
case 2:
myVgl=new VglNaam();
break;
case 3:
myVgl=new VglVoorNaam();
break;
case 4:
myVgl=new VglGebDat();
break;
Public Class Form1
Inherits System.Windows.Forms.Form
#Region " Windows Form Designer generated code "
Public Sub New()
MyBase.New()
'This call is required by the Windows Form Designer.
InitializeComponent()
'Add any initialization after the InitializeComponent() call
End Sub
'Form overrides dispose to clean up the component list.
Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
If disposing Then
If Not (components Is Nothing) Then
components.Dispose()
End If
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.
Friend WithEvents lvListView As System.Windows.Forms.ListView
<System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
Me.lvListView = New System.Windows.Forms.ListView
Me.SuspendLayout()
'
'lvListView
'
Me.lvListView.Location = New System.Drawing.Point(8,
Me.lvListView.Name = "lvListView"
Me.lvListView.Size = New System.Drawing.Size(272, 248)
Me.lvListView.TabIndex = 0
'
'Form1
'
Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)
Me.ClientSize = New System.Drawing.Size(292, 273)
Me.Controls.Add(Me.lvListView)
Me.Name = "Form1"
Me.Text = "Sorting a ListView"
Me.ResumeLayout(False)
End Sub
#End Region
Dim sPoe As String = "The thousand injuries of Fortunate " & "I had borne as I best could; but when he ventured " & "upon insult, I vowed revenge"
'Каждое слово строки помещается в массив.
Dim aPoe() As String = sPoe.Split(" ")
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Dim iColumn As Integer
Dim iLength As Integer = aPoe.Length - 1
Dim item1 As ListViewItem
Dim dDate As Date = Today
Dim sDate As String
buildListView()
For iColumn = 0 To iLength
item1 = New ListViewItem(iColumn * 22)
item1.SubItems.Add(dDate.AddDays(iColumn * 47))
item1.SubItems.Add(aPoe(iColumn))
lvListView.Items.Add(item1)
Next
End Sub
Private Sub buildListView()
With lvListView
' Очистка списка.
.Items.Clear()
' Установка вида "таблица".
.View = View.Details
' Это свойство позволяет менять столбцы местами.
.AllowColumnReorder = True
' При выборе элемента вместе с ним будут выделяться и его подэлементы.
.FullRowSelect = True
' Включить отображение сетки,
.GridLines = True
' Сортировать элементы списка по возрастанию.
.Sorting = SortOrder.Ascending
.Columns.Add("Numbers", lvListView.Width \ 3, HorizontalAlignment.Left)
.Columns.Add("Dates", lvListView.Width \ 3, HorizontalAlignment.Left)
.Columns.Add("Strings", (lvListView.Width \ 3) - 22, HorizontalAlignment.Left)
End With
End Sub
Private Sub lvListView_ColumnClick(ByVal sender As Object, ByVal e As System.Windows.Forms.ColumnClickEventArgs) Handles lvListView.ColumnClick
Static bDirection As Boolean = False
lvListView.ListViewItemSorter = New SortRoutines.CompareListViewItems(e.Column, lvListView)
If bDirection = False Then
lvListView.Sorting = SortOrder.Descending
Else
lvListView.Sorting = SortOrder.Ascending
End If
lvListView.Sort()
bDirection = Not bDirection
End Sub
End Class
Public Class SortRoutines
Public Class CompareListViewItems
Implements IComparer
Shared bSortDirection As Boolean = True 'обьявлена как шаред чтобы сохранить свое значение между вызовами класса
Dim sRoutineToUse As String = "String" 'определяет тип сортировки - текст, номер, дата.
Dim LView As ListView 'обрабатываемый элемент управления
Dim iColumn As Integer 'сортируемый столбец
Dim lvCollection As ListView.ListViewItemCollection
Dim bSafeToSort As Boolean = False
Sub New(ByVal itemlndex As Integer, ByVal lvListView As ListView)
iColumn = itemlndex
LView = lvListView
bSortDirection = Not bSortDirection
lvCollection = New ListView.ListViewItemCollection(lvListView)
determineType()
End Sub
Private Function determineType() As Boolean
'Чтобы сортировка имела смысл, должно быть хотя бы 2 элемента.
If (LView.Items.Count < 2) Then
bSafeToSort = False
Return False
End If
'Если значение равно Null, подэлемент, наверное, не добавлен.
If (checkForNull() = True) Then
bSafeToSort = False
Return False
End If
'Если все элементы имеют значения, надо определить их тип.
If (isItADate() = True) Then
sRoutineToUse = "Date"
ElseIf (isItANumber() = True) Then
sRoutineToUse = "Number"
Else
sRoutineToUse = "String"
End If
End Function
Private Function checkForNull() As Boolean
Dim lvTest As ListViewItem
Dim sItemContents As String
For Each lvTest In lvCollection
Try
If iColumn = 0 Then
sItemContents = lvTest.Text
Else
sItemContents = lvTest.SubItems(iColumn).Text
End If
Catch
Return True
End Try
Next
bSafeToSort = True
Return False 'все в порядке
End Function
Private Function isItADate() As Boolean
Dim lvTest As ListViewItem 'объект для просмотра элементов
Dim oObjectToTest As Object 'объект для проверки типа
Dim sItemContents As String 'содержание элемента
'Просмотр всех элементов.
For Each lvTest In lvCollection
If iColumn = 0 Then
sItemContents = lvTest.Text
Else
sItemContents = lvTest.SubItems(iColumn).Text
End If
Try
oObjectToTest = CDate(sItemContents)
Catch
Return False
End Try
Next
Return True
End Function
Private Function isItANumber() As Boolean
Dim lvTest As ListViewItem 'объект для просмотра элементов
Dim oObjectToTest As Object 'объект для проверки типа
Dim sItemContents As String 'содержание элемента
' Просмотр всех элементов.
For Each lvTest In lvCollection
If iColumn = 0 Then
sItemContents = lvTest.Text
Else
sItemContents = lvTest.SubItems(iColumn).Text
End If
Try
oObjectToTest = CDbl(sItemContents)
Catch
Return False
End Try
Next
Return True
End Function
Function compare(ByVal oFirst As Object, ByVal oSecond As Object) As Integer Implements System.Collections.IComparer.Compare
If bSafeToSort = False Then Exit Function
Dim lvElement1 As ListViewItem = CType(oFirst, ListViewItem)
Dim lvElement2 As ListViewItem = CType(oSecond, ListViewItem)
If sRoutineToUse = "String" Then
If bSortDirection = True Then
If iColumn = 0 Then
Return String.Compare(lvElement1.Text, lvElement2.Text)
Else
Return String.Compare(lvElement1.SubItems(iColumn).Text, lvElement2.SubItems(iColumn).Text)
End If
Else
If iColumn = 0 Then
Return String.Compare(lvElement2.Text, lvElement1.Text)
Else
Return String.Compare(lvElement2.SubItems(iColumn).Text, lvElement1.SubItems(iColumn).Text)
End If
End If
ElseIf sRoutineToUse = "Number" Then
If bSortDirection = True Then
If iColumn = 0 Then
Return Math.Sign(CLng(lvElement1.Text - lvElement2.Text))
Else
Return Math.Sign(CLng(lvElement1.SubItems(iColumn).Text - lvElement2.SubItems(iColumn).Text))
End If
Else
If iColumn = 0 Then
Return Math.Sign(CLng(lvElement2.Text - lvElement1.Text))
Else
Return Math.Sign(CLng(lvElement2.SubItems(iColumn).Text - lvElement1.SubItems(iColumn).Text))
End If
End If
Else 'Это дата
If bSortDirection = True Then
If iColumn = 0 Then
Return Date.Compare(Date.Parse(lvElement1.Text), Date.Parse(lvElement2.Text))
Else
Return Date.Compare(Date.Parse(lvElement1.SubItems(iColumn).Text), Date.Parse(lvElement2.SubItems(iColumn).Text))
End If
Else
If iColumn = 0 Then
Return Date.Compare(Date.Parse(lvElement2.Text), Date.Parse(lvElement1.Text))
Else
Return Date.Compare(Date.Parse(lvElement2.SubItems(iColumn).Text), Date.Parse(lvElement1.SubItems(iColumn).Text))
End If
End If
End If
End Function
End Class
End Class
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 110