Sorting a Listview by colums

how can I sort a listbox by clicking a column? I've tried changing the columsclick event, but unsucessfuly. How can I do it. Thanks.
LVL 1
jpcsAsked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

mayhewCommented:
Is it that you want to sort the whole listbox by clicking on any column?

If so, in the ListBox1OnClick method:
  ListBox1.Sorted := true;

If I am misunderstanding your question, please rephrase it and we'll take another look.  :)
bomeCommented:
I assume that your listbox is a TListView. Let's call it ListView:
Create handlers for OnColumnClick and OnCompare:

procedure TForm1.ListViewColumnClick(Sender: TObject;
  Column: TListColumn);
begin
 ListView.CustomSort(nil,Column.index);
end;


procedure TForm1.ListViewCompare(Sender: TObject; Item1,
  Item2: TListItem; Data: Integer; var Compare: Integer);
begin
 if (Item1=nil) and (Item2=nil) then
  Compare:=0
 else
 if (Item1=nil) and (Item2<>nil) then
  Compare:=-1
 else
 if (Item1<>nil) and (Item2=nil) then
  Compare:=1
 else
 if Data=0 then
  Compare:=ComPareStr(Item1.Caption,Item2.Caption)
 else
 // sanity check
 if (Data<=Item1.SubItems.Count) and (Data<=Item2.SubItems.Count) then
  Compare:=ComPareStr(Item1.SubItems[Data-1],Item2.SubItems[Data-1]);
 // sort by name as second criteria
 if (Compare=0) and (Data<>0) then
  ListViewCompare(sender,Item1,Item2,0,Compare);
end;

These procedures sort alphanumerically the respective column when you click on the column header.

bome

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
jpcsAuthor Commented:
Thanks for the grat answer bome. Gee, It's was far more dificult than I thought.

There are some tinny little problems that I would thank you if you help me :

1. If I click a column, it does now sort the items (from a to z), but if I click it again, it should resort from z to a. How can I do it?

2. Why is "T" (upcase) before "a" (lowercase) and why is "2" after "10"? How can I solve this? (I don't want to use "02" instead "2".


Thank you very much for your answer.

Amazon Web Services

Are you thinking about creating an Amazon Web Services account for your business? Not sure where to start? In this course you’ll get an overview of the history of AWS and take a tour of their user interface.

jpcsAuthor Commented:
Sorry everybody, but in fact it is a ListView control, not a ListBox. Sorry.
bomeCommented:
Hi,
no problem.
1. add 2 variables to your form: e.g.
sortIndex: Integer;
reversesort:boolean;

in the ColumnsClick handler you add at the beginning:
if sortIndex=Column.index then
 reverseSort:=not reverseSort;
sortIndex:=Column.Index;

Replace the last 2 lines in the ListViewCompare procedure with these:
if (Compare=0) and (Data<>0) then
      ListViewCompare(sender,Item1,Item2,0,Compare)
else
if reverseSort then
 Compare:=-Compare;

2. To have case insensitive sort, replace all CompareStr with CompareText.

That's it, thank you for the points !
bome
jpcsAuthor Commented:
Thanks.
jpcsAuthor Commented:
Just another thing : Can you tell me how to avoid the user to resize any column header?

Thanks
bomeCommented:
no, I don't. I think this is intended by Microsoft - try Ctrl+'+' - it resizes automatically. So you would have to care about some events. The only thing I can imagine is to access the listview directly with windows API - I don't have the time at the moment to check this out. The names of these "functions" start all with "ListView_"...

Another thing why this could get a problem: Column width is in pixels - but what if the user changes the standard font size ? I haven't tried, but very probably the column titles change size, too, so eventually the user wouldn't be able to read the column title when he has big fonts.

bome
bomeCommented:
no, I don't. I think this is intended by Microsoft - try Ctrl+'+' - it resizes automatically. So you would have to care about some events. The only thing I can imagine is to access the listview directly with windows API - I don't have the time at the moment to check this out. The names of these "functions" start all with "ListView_"...

Another thing why this could get a problem: Column width is in pixels - but what if the user changes the standard font size ? I haven't tried, but very probably the column titles change size, too, so eventually the user wouldn't be able to read the column title when he has big fonts.

bome
ibrobarCommented:
Dear Bome

I want to thank u for the great solution and for your help
I am having a problem with a listview too let me explain it
I have a listview with 6 static columns.
I have a popup menu attached with the listview.From the popup menu i can call listbox showing table fields.
what I need to do is to drag and drop from that listbox to the listview and to get the effects due to the drag and drop event.
here is my code: {I applied this code on listviewDragdrop procedure}

var I:integer;
    NewColumn: TListColumn;
    ListItem:TListItem;
    S:String;
begin
if (sender=listview1) and (source=form10.ListBox1) then
For i := 0 to (Form10.ListBox1.Items.Count - 1) do begin
   if Form10.ListBox1.Selected[i] then begin
      NewColumn:= listview1.Columns.add;
      NewColumn.Caption :=Form10.listbox1.items.Strings[i];
      NewColumn.Width:=100;
      S:=Form10.listbox1.items.Strings[i];
   end;
end;
DataModule1.Query13.Open;
If DataModule1.Query13.RecordCount<>0 then begin
     ListView1.Items.Clear;
     DataModule1.Query13.First;
    while not DataModule1.QUERY13.EOF do begin
       listitem:=Form2.listview1.Items.Add;
       listitem.Caption:=DataModule1.Query13['TITLE'];
       listitem.SubItems.Add(DataModule1.Query13['atitle']);
       listitem.SubItems.Add(DataModule1.Query13['borrower']);
       listitem.SubItems.Add(DataModule1.Query13['overdue']);
       listitem.SubItems.Add(DataModule1.Query13['cdate']);
       listitem.SubItems.Add(DataModule1.Query13['bdepartment']);
       Listitem.SubItems.Add(DataModule1.Query13[s]);
       listitem.ImageIndex:=0;
       DataModule1.QUERY13.Next;
   end;
end

as you can see from my code that I am adding new columns with out having any problems and i can add one subitems prefectly but when I want to drag and drop another item from the listbox the new subitems is coming over the old one cause you know it's coming at the end of the listview items.
I tried the insert procedure it didn't work , I tried many loops but I am still having the same problem
so can I get your help here.
one more thing how can  save the new layout of the listview so i can ask get again when I want the same layout.

thanks a lot

regards
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Delphi

From novice to tech pro — start learning today.