ListView 如何排序 像资源管理器那样对 Subitem 的内容进行排序。 最好自己来控制排序 ,如下所示 : function CustomSortProc( Item1, Item2 : TListItem; lParam : LongInt ) : Integer; stdcall;begin if lParam >= 0 then //lParam 中保存的是 SubItem 的 Index begin result := -CompareText(Item1.SubItems.Strings[lParam], Item1.SubItems.Strings[lParam] ); end else result := 0;end; 在 ListView 的 ColumnClick 事件响应方法中输入 CustomSort(@CustomSortProc, Column.Index );
这是自己写的一个控件,点击列标题进行排序,不过在运行时如果那一列是string类型的,会报错,但没有关系,编译成应用程序后就不会报错了。unit ListView1;interfaceuses Windows, Messages, SysUtils, Variants, Classes, Controls, ComCtrls, Graphics, Forms, Dialogs, StdCtrls;type tfield=record name: array[0..100] of string; end; type TListView1 = class(TListView) private item:tlistitem; p:^tfield; fieldslist:tlist; list:tstringlist; wcol: array[0..100] of integer; usersort,bmode:boolean; function GetDataType(i,n:integer):integer;//i表示比较的列;n表示比较的类型 protected procedure ColClick(Column: TListColumn); override; procedure ColRightClick(Column: TListColumn; Point: TPoint); override; { Protected declarations } public constructor Create(aowner:tcomponent);override; { Public declarations } published { Published declarations } end;procedure Register;implementation procedure Register; begin RegisterComponents('Samples', [TListView1]); end;{ TListView1 }constructor TListView1.Create(aowner: tcomponent); begin inherited; usersort:=true; bmode:=true;//默认排序为升序 end;
procedure TListView1.ColClick(Column: TListColumn); var m,n,col,smode,rcount,fcount,dtype:integer; begin if Items.Count<=0 then exit;//如果列表中没有数据则退出 rcount:=Items.Count;//获取行(记录)数 fcount:=Columns.Count;//获取列(字段)数 //第一次排序时保存各字段的显示长度 if usersort then begin for m:=0 to fcount-1 do wcol[m]:=Columns.Items[m].Width;//保存各字段的显示长度 end; usersort:=false; //获取列表中的数据到fieldslist记录集中 fieldslist:=tlist.Create; for m:=0 to rcount-1 do begin new(p); ItemIndex:=m; item:=items[m]; p.name[0]:=item.Caption; for n:=0 to fCount-2 do p.name[n+1]:=item.SubItems[n]; fieldslist.Add(p); end; //获取用户需要排序的列号 col:=Column.ID; //获取排序的方式 if bmode then begin smode:=0; bmode:=false; end else begin smode:=1; bmode:=true; end; //获取需要排序的列按何种数据类型进行(0字符型,1数值型,2日期型) dtype:=GetDataType(col,1); if dtype=-1 then begin dtype:=GetDataType(col,2); if dtype=-1 then dtype:=0; end; //对fieldslist记录集中的数据的指定列进行相应的数据类型的排序 for m:=0 to fieldslist.Count-2 do for n:=m+1 to fieldslist.Count-1 do begin case smode of 0:begin case dtype of 0:begin if tfield(fieldslist.Items[m]^).name[col]>tfield(fieldslist.Items[n]^).name[col] then fieldslist.Exchange(m,n); end; 1:begin if strtofloat(tfield(fieldslist.Items[m]^).name[col])>strtofloat(tfield(fieldslist.Items[n]^).name[col]) then fieldslist.Exchange(m,n); end; 2:begin if strtodatetime(tfield(fieldslist.Items[m]^).name[col])>strtodatetime(tfield(fieldslist.Items[n]^).name[col]) then fieldslist.Exchange(m,n); end; end; end; 1:begin case dtype of 0:begin if tfield(fieldslist.Items[m]^).name[col]<tfield(fieldslist.Items[n]^).name[col] then fieldslist.Exchange(m,n); end; 1:begin if strtofloat(tfield(fieldslist.Items[m]^).name[col])<strtofloat(tfield(fieldslist.Items[n]^).name[col]) then fieldslist.Exchange(m,n); end; 2:begin if strtodatetime(tfield(fieldslist.Items[m]^).name[col])<strtodatetime(tfield(fieldslist.Items[n]^).name[col]) then fieldslist.Exchange(m,n); end; end; end; end; end; //把排好序的数据回写至列表中显示 Clear; for m:=0 to fieldslist.Count-1 do begin item:=Items.Add; item.Caption:=tfield(fieldslist.Items[m]^).name[0]; for n:=1 to fCount-1 do item.SubItems.Add(tfield(fieldslist.Items[m]^).name[n]); end; //继承原有的事件 inherited; end;//获取需要排序的列按何种数据类型进行(0字符型,1数值型,2日期型) function TListView1.GetDataType(i,n:integer):integer;//i表示比较的列;n表示比较的类型 var m:integer; {a:double; b:tdatetime;} begin result:=-1; for m:=0 to fieldslist.Count-1 do begin case n of 1:begin result:=1; try strtofloat(tfield(fieldslist.Items[m]^).name[i]); except result:=-1; break; end; end; 2:begin result:=2; try strtodatetime(tfield(fieldslist.Items[m]^).name[i]); except result:=-1; break; end; end; end; end; end;end.中间还有一个函数是用来点击右键时根据listview中的内容弹出一个通用排序窗口用的,如果大家需要,我下次再帖吧
像资源管理器那样对 Subitem 的内容进行排序。 最好自己来控制排序 ,如下所示 :
function CustomSortProc( Item1, Item2 : TListItem; lParam : LongInt ) : Integer; stdcall;begin if lParam >= 0 then //lParam 中保存的是 SubItem 的 Index begin result := -CompareText(Item1.SubItems.Strings[lParam], Item1.SubItems.Strings[lParam] ); end else result := 0;end;
在 ListView 的 ColumnClick 事件响应方法中输入 CustomSort(@CustomSortProc, Column.Index );
Windows, Messages, SysUtils, Variants, Classes, Controls, ComCtrls, Graphics,
Forms, Dialogs, StdCtrls;type
tfield=record
name: array[0..100] of string;
end;
type
TListView1 = class(TListView)
private
item:tlistitem;
p:^tfield;
fieldslist:tlist;
list:tstringlist;
wcol: array[0..100] of integer;
usersort,bmode:boolean;
function GetDataType(i,n:integer):integer;//i表示比较的列;n表示比较的类型
protected
procedure ColClick(Column: TListColumn); override;
procedure ColRightClick(Column: TListColumn; Point: TPoint); override;
{ Protected declarations }
public
constructor Create(aowner:tcomponent);override;
{ Public declarations }
published
{ Published declarations }
end;procedure Register;implementation
procedure Register;
begin
RegisterComponents('Samples', [TListView1]);
end;{ TListView1 }constructor TListView1.Create(aowner: tcomponent);
begin
inherited;
usersort:=true;
bmode:=true;//默认排序为升序
end;
procedure TListView1.ColClick(Column: TListColumn);
var
m,n,col,smode,rcount,fcount,dtype:integer;
begin
if Items.Count<=0 then exit;//如果列表中没有数据则退出
rcount:=Items.Count;//获取行(记录)数
fcount:=Columns.Count;//获取列(字段)数
//第一次排序时保存各字段的显示长度
if usersort then
begin
for m:=0 to fcount-1 do
wcol[m]:=Columns.Items[m].Width;//保存各字段的显示长度
end;
usersort:=false;
//获取列表中的数据到fieldslist记录集中
fieldslist:=tlist.Create;
for m:=0 to rcount-1 do
begin
new(p);
ItemIndex:=m;
item:=items[m];
p.name[0]:=item.Caption;
for n:=0 to fCount-2 do
p.name[n+1]:=item.SubItems[n];
fieldslist.Add(p);
end;
//获取用户需要排序的列号
col:=Column.ID;
//获取排序的方式
if bmode then
begin
smode:=0;
bmode:=false;
end
else
begin
smode:=1;
bmode:=true;
end;
//获取需要排序的列按何种数据类型进行(0字符型,1数值型,2日期型)
dtype:=GetDataType(col,1);
if dtype=-1 then
begin
dtype:=GetDataType(col,2);
if dtype=-1 then
dtype:=0;
end;
//对fieldslist记录集中的数据的指定列进行相应的数据类型的排序
for m:=0 to fieldslist.Count-2 do
for n:=m+1 to fieldslist.Count-1 do
begin
case smode of
0:begin
case dtype of
0:begin
if tfield(fieldslist.Items[m]^).name[col]>tfield(fieldslist.Items[n]^).name[col] then
fieldslist.Exchange(m,n);
end;
1:begin
if strtofloat(tfield(fieldslist.Items[m]^).name[col])>strtofloat(tfield(fieldslist.Items[n]^).name[col]) then
fieldslist.Exchange(m,n);
end;
2:begin
if strtodatetime(tfield(fieldslist.Items[m]^).name[col])>strtodatetime(tfield(fieldslist.Items[n]^).name[col]) then
fieldslist.Exchange(m,n);
end;
end;
end;
1:begin
case dtype of
0:begin
if tfield(fieldslist.Items[m]^).name[col]<tfield(fieldslist.Items[n]^).name[col] then
fieldslist.Exchange(m,n);
end;
1:begin
if strtofloat(tfield(fieldslist.Items[m]^).name[col])<strtofloat(tfield(fieldslist.Items[n]^).name[col]) then
fieldslist.Exchange(m,n);
end;
2:begin
if strtodatetime(tfield(fieldslist.Items[m]^).name[col])<strtodatetime(tfield(fieldslist.Items[n]^).name[col]) then
fieldslist.Exchange(m,n);
end;
end;
end;
end;
end;
//把排好序的数据回写至列表中显示
Clear;
for m:=0 to fieldslist.Count-1 do
begin
item:=Items.Add;
item.Caption:=tfield(fieldslist.Items[m]^).name[0];
for n:=1 to fCount-1 do
item.SubItems.Add(tfield(fieldslist.Items[m]^).name[n]);
end;
//继承原有的事件
inherited;
end;//获取需要排序的列按何种数据类型进行(0字符型,1数值型,2日期型)
function TListView1.GetDataType(i,n:integer):integer;//i表示比较的列;n表示比较的类型
var
m:integer;
{a:double;
b:tdatetime;}
begin
result:=-1;
for m:=0 to fieldslist.Count-1 do
begin
case n of
1:begin
result:=1;
try
strtofloat(tfield(fieldslist.Items[m]^).name[i]);
except
result:=-1;
break;
end;
end;
2:begin
result:=2;
try
strtodatetime(tfield(fieldslist.Items[m]^).name[i]);
except
result:=-1;
break;
end;
end;
end;
end;
end;end.中间还有一个函数是用来点击右键时根据listview中的内容弹出一个通用排序窗口用的,如果大家需要,我下次再帖吧