Link to home
Start Free TrialLog in
Avatar of jaygan
jaygan

asked on

Rearranging columns in TListView

Is there an easy way to rearrange columns of TListView?

Say, I have 3 columns:

   A  Caption
   B  SubString[0]
   C  SubString[1]
   D  SubString[2]

Is there a way to make C be displayed first before B without needing to transfer the the contents of the substrings between 0 and 1?

   A  Caption
   C  SubString[1]
   B  SubString[0]
   D  SubString[2]
 
And is there a way to do this in such a way that the user can drag-and-drop the columns to re-arrange it?

Thanks!

Regards,
Jay
Avatar of esoftbg
esoftbg
Flag of Bulgaria image

unit Unit_Q_20998498;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ComCtrls, Buttons;

type
  TForm1 = class(TForm)
    ListView1: TListView;
    SpeedButton1: TSpeedButton;
    procedure SpeedButton1Click(Sender: TObject);
  private{ Private declarations }
  public { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.SpeedButton1Click(Sender: TObject);
var
  C:      Integer;
  I:      Integer;
  NewCol: TListColumn;
  NewItem:TListItem;
begin
  C := ListView1.Columns.Count;
  for I := 0 to C-1 do
    NewCol := ListView1.Columns.Add;
  ListView1.Columns.Items[3].Caption := ListView1.Columns.Items[0].Caption;
  ListView1.Columns.Items[4].Caption := ListView1.Columns.Items[2].Caption;
  ListView1.Columns.Items[5].Caption := ListView1.Columns.Items[1].Caption;
  ListView1.Columns.Items[3].Width := ListView1.Columns.Items[0].Width;
  ListView1.Columns.Items[4].Width := ListView1.Columns.Items[2].Width;
  ListView1.Columns.Items[5].Width := ListView1.Columns.Items[1].Width;
  for I := 0 to C-1 do
    ListView1.Columns.Delete(0);

  C := ListView1.Items.Count;
  for I := 0 to C-1 do
  begin
    NewItem := ListView1.Items.Add;
    ListView1.Items[I+3] := ListView1.Items[I];
    NewItem.SubItems.Add(ListView1.Items[I].SubItems[0]);
    NewItem.SubItems.Add(ListView1.Items[I].SubItems[1]);
  end;

  ListView1.Items[3] := ListView1.Items[1];
  ListView1.Items[4] := ListView1.Items[0];
  ListView1.Items[5] := ListView1.Items[2];

  ListView1.Items[3].SubItems[0] := ListView1.Items[1].SubItems[1];
  ListView1.Items[4].SubItems[0] := ListView1.Items[0].SubItems[1];
  ListView1.Items[5].SubItems[0] := ListView1.Items[2].SubItems[1];

  ListView1.Items[3].SubItems[1] := ListView1.Items[1].SubItems[0];
  ListView1.Items[4].SubItems[1] := ListView1.Items[0].SubItems[0];
  ListView1.Items[5].SubItems[1] := ListView1.Items[2].SubItems[0];
  for I := 0 to C-1 do
    ListView1.Items[0].Delete;
end;

end.
above example at:        http://www.geocities.com/esoftbg/
                    link:        Q_20998498.zip
Avatar of jaygan
jaygan

ASKER

Sorry esoftbg, I think I wan't clear in my explanation-- but thank you very much for trying to answer it.

What I meant by the lines with ABCD are the variables for the column values-- that how the items is stored in the subitems (my mistake, it isn't substring) doesn't change-- only their arrangement when being displayed in the screen is.

That is, say I have a Listitem where
    caption:='A''; subitems[0]:='B'; subitems[1]:='C'; subitems[2]:='D'

Normally, this would be displayed as:
     Column        1       2       3      4
                        A      B       C      D

I want the user to be able to drag column 3 and put it before column 2 such that it would be displayed as
     Column        1       3       2      4
                        A       C      B      D

However, I don't want to swap the values between subitems[0] and subitems[1]. The reason, unfortunately, being that I have already coded a lot of the program and have been basing a lot of logic on the exact position of each of the values. Say, if I have subitems[1], I would always assume that it would return B-- not C even if the columns has been re-arranged.
           
unit Unit_Q_20998498;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ComCtrls, Buttons;

type
  TForm1 = class(TForm)
    ListView1: TListView;
    SpeedButton1: TSpeedButton;
    procedure SpeedButton1Click(Sender: TObject);
  private{ Private declarations }
  public { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.SpeedButton1Click(Sender: TObject);
var
  C:      Integer;
  I:      Integer;
  NewCol: TListColumn;
  NewItem:TListItem;
begin
  ListView1.Hide;
  try
    C := ListView1.Columns.Count;
    for I := 0 to C-1 do
      NewCol := ListView1.Columns.Add;
    ListView1.Columns.Items[4].Caption := ListView1.Columns.Items[0].Caption;
    ListView1.Columns.Items[5].Caption := ListView1.Columns.Items[2].Caption;
    ListView1.Columns.Items[6].Caption := ListView1.Columns.Items[1].Caption;
    ListView1.Columns.Items[7].Caption := ListView1.Columns.Items[3].Caption;
    ListView1.Columns.Items[4].Width := ListView1.Columns.Items[0].Width;
    ListView1.Columns.Items[5].Width := ListView1.Columns.Items[2].Width;
    ListView1.Columns.Items[6].Width := ListView1.Columns.Items[1].Width;
    ListView1.Columns.Items[7].Width := ListView1.Columns.Items[3].Width;
    for I := 0 to C-1 do
      ListView1.Columns.Delete(0);

    NewItem := ListView1.Items.Add;
    ListView1.Items[1] := ListView1.Items[0];
    NewItem.SubItems.Add(ListView1.Items[1].SubItems[0]);

    ListView1.Items[1] := ListView1.Items[0];

    ListView1.Items[1].SubItems[0] := ListView1.Items[0].SubItems[1];

    ListView1.Items[1].SubItems[1] := ListView1.Items[0].SubItems[0];

    ListView1.Items[0].Delete;
  finally
    ListView1.Show;
  end;
end;

end.

//........

object Form1: TForm1
  Left = 254
  Top = 128
  BorderIcons = [biSystemMenu, biMinimize]
  BorderStyle = bsSingle
  Caption = 'Form1'
  ClientHeight = 190
  ClientWidth = 338
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'MS Sans Serif'
  Font.Style = []
  OldCreateOrder = False
  PixelsPerInch = 96
  TextHeight = 13
  object SpeedButton1: TSpeedButton
    Left = 16
    Top = 4
    Width = 128
    Height = 22
    Caption = 'Rearranging'
    OnClick = SpeedButton1Click
  end
  object ListView1: TListView
    Left = 16
    Top = 32
    Width = 250
    Height = 128
    Columns = <
      item
        Caption = '1'
        Width = 32
      end
      item
        Caption = '2'
        Width = 64
      end
      item
        Caption = '3'
        Width = 64
      end
      item
        Caption = '4'
        Width = 80
      end>
    GridLines = True
    Items.Data = {
      3E0000000100000000000000FFFFFFFFFFFFFFFF0300000000000000034D5456
      054B796C6965074D696E6F677565094175737472616C6961FFFFFFFFFFFF}
    TabOrder = 0
    ViewStyle = vsReport
  end
end
Avatar of jaygan

ASKER

That workaround will seem to work. However, I'm not sure if that would be the best way considering that it needs to maintain the data in memory twice =(

I have seem a lot of programs with this type of functionality-- wherein people can simply drag and drop the columns to re-arrange it. It doesn't seem to be the simple vsReport type of ListView and I can't seem to find the right component for it-- if it is standard windows at all.

Hope someone can give advise on this. Although it will be a real pain, I'm OK to re-code a whole chunck of code if it would be the best way to add this functionality...
ASKER CERTIFIED SOLUTION
Avatar of esoftbg
esoftbg
Flag of Bulgaria image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
>This function is more easy to use:
This procedure is more easy to use:

Avatar of jaygan

ASKER

Sorry to give you only an average score since it's really more like a workaround.

But I do thank you for the help you have provided =)