Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Общие вопросы > VirtualTreeView Ручная сортировка


Автор: CHERRY 4.5.2012, 15:29
VirtualTreeView - типа файловый менеджер. Необходимо после заполнения сразу отсортировывать список. По клику на заголовках колонок сортировка работает отлично.
Код

procedure TForm1.VTHeaderClick(Sender: TVTHeader; HitInfo: TVTHeaderHitInfo);
begin
  With HitInfo Do
  Begin

    if Button = mbLeft then
    begin
      // Меняем индекс сортирующей колонки на индекс колонки,
      // которая была нажата.
      VT.Header.SortColumn := Column;
      // Сортируем всё дерево относительно этой колонки
      // и изменяем порядок сортировки на противополжный
      if VT.Header.SortDirection = sdAscending then
      begin
        VT.Header.SortDirection := sdDescending;
        VT.SortTree(Column, VT.Header.SortDirection);
      end
      else
      begin
        VT.Header.SortDirection := sdAscending;
        VT.SortTree(Column, VT.Header.SortDirection);
      end;
    end;

  End;
end;

procedure TForm1.VTCompareNodes(Sender: TBaseVirtualTree;
  Node1, Node2: PVirtualNode; Column: TColumnIndex; var Result: Integer);
Var
  Name1, Name2: String;
  Attr1, Attr2: String;
  Size1, Size2:Int64;
  Date1, Date2: TDateTime;
  i1, i2: Integer;
  Data1, Data2: PFMItem;
  HitInfo: TVTHeaderHitInfo;
begin
  Data1 := Sender.GetNodeData(Node1);
  Data2 := Sender.GetNodeData(Node2);

  i1 := Pos('-D', Data1^.Attr);
  i2 := Pos('-D', Data2^.Attr);
  Name1 := LowerCase(Data1^.Name);
  Name2 := LowerCase(Data2^.Name);

  Size1 := StrToInt64Def(Data1^.Size,0);
  Size2 := StrToInt64Def(Data2^.Size,0);

  Date1 := strtodatetime(Data1^.Date);
  Date2 := strtodatetime(Data2^.Date);

  Attr1 := LowerCase(Data1^.Attr);
  Attr2 := LowerCase(Data2^.Attr);

  Result := 0;

  case Column of
    0://Сортировка по имени
      Begin
        // Сортируем папки
        if (i1 > 0) and (i2 > 0) then
        Begin
          if Name1 > Name2      then Result := 1
          else if Name1 < Name2 then Result := -1;
        End;

        // Сортируем файлы
        if (i1 = 0) and (i1 = 0) then // для файлов
          if Name1 > Name2      then Result := 1
          else if Name1 < Name2 then Result := -1
      end;

    1://Сортировка по размеру
      Begin
        // Сортируем папки
        if (i1 > 0) and (i2 > 0) then
        Begin
          if Size1 > Size2      then Result := 1
          else if Size1 < Size2 then Result := -1;
        End;

        // Сортируем файлы
        if (i1 = 0) and (i1 = 0) then // для файлов
          if Size1 > Size2      then Result := 1
          else if Size1 < Size2 then Result := -1
      End;

    2://Сортировка по дате
      Begin
        // Сортируем папки
        if (i1 > 0) and (i2 > 0) then
        Begin
          if Date1 > Date2      then Result := 1
          else if Date1 < Date2 then Result := -1;
        End;

        // Сортируем файлы
        if (i1 = 0) and (i1 = 0) then // для файлов
          if Date1 > Date2      then Result := 1
          else if Date1 < Date2 then Result := -1
      End;

    3://Сортировка по аттрибутам
      Begin
        // Сортируем папки
        if (i1 > 0) and (i2 > 0) then
        Begin
          if Attr1 > Attr2      then Result := 1
          else if Attr1 < Attr2 then Result := -1;
        End;

        // Сортируем файлы
        if (i1 = 0) and (i1 = 0) then // для файлов
          if Attr1 > Attr2      then Result := 1
          else if Attr1 < Attr2 then Result := -1
      End;
  end;
  // корень всегда вверху
  // при обратной сортировке делаем реверс кузультата
  // для корневой точки '..'
  if VT.Header.SortDirection = sdAscending then
  begin
    if (Name2 = '..')      then Result := 1
    else if (Name1 = '..') then Result := -1
  end
  else
  Begin
    if (Name2 = '..')      then Result := -1
    else if (Name1 = '..') then Result := 1
  End;

end;


Повесил сортировку на кнопку
Код

procedure TForm1.Button2Click(Sender: TObject);
begin
  VT.Header.SortColumn := 0;
  VT.SortTree(0, sdAscending, true);
end;

Не сортируется.
Как сделать, чтобі список сортировался без клика по заголовку?

Автор: XperT 4.5.2012, 17:30
Попробуйте так:
Код

VT.BeginUpdate();
try
  VT.Header.SortColumn := 0;
  VT.SortTree(0, sdAscending, true);
finally
  VT.EndUpdate();
end;


Если не поможет, значит что-то у вас не так, потому что у меня прекрасно сортирует используя такой код:
Код

VT.SortTree(0, sdAscending);

Автор: CHERRY 4.5.2012, 21:43
В том то и фишка, что что-то не так! Не работает ваш код. 
Я думаю, что конструкция
Код

VT.BeginUpdate;
..........................
VT.EndUpdate;

нужна, чтобы не возникало "лишнего" мерцания.
TVirtualStringTree - богатый на различные настройки компонент. Возможно есть что-то типа 
VT.Options.Штучка, что решает проблему. Я найти такую штучку пока не смог. Поэтому и взываю к помощи.
Найду сам решение  - отпишусь. 

Автор: CHERRY 4.5.2012, 22:02
Причем, что интересно. 
Если кликом по хидеру отсортировать колонку в направлении sdDescending
код
Код

procedure TForm1.Button2Click(Sender: TObject);
begin
VT.BeginUpdate;
try
  VT.Header.SortColumn := 0;
  VT.SortTree(0, sdAscending, true);
finally
  VT.EndUpdate;
end;
end;

отсортировует колонку в соответствии со своим направлением(sdAscending).
Естественно конструкции (VT.BeginUpdate;  VT.EndUpdate;) не имеют значения.
Т.е. сортировка VT.SortTree(0, sdAscending, true); работает, но не всегда.

Автор: XperT 4.5.2012, 22:22
Есть предположение, что колонка, по которой идёт сортировка при клике на хидер отличается от 0.

Автор: CHERRY 6.5.2012, 19:20
Нет, с колонками все в порядке. Но спасибо, мысль здравая. Я понял, что проблема в алгоритме сортировки, поскольку VTCompareNodes
отрабатывает, но в зависимости от состояния списка(файлы-папки) есть неучтенные ситуации(папка-файл, файл-папка). Задача сортировки состоит в том, чтобы папки сортировались отдельно от файлов и находились всегда в начале списка, а файлы сортировались сами по себе и находились всегда после папок, кроме того "точка корня ".."" должна быть всегда вверху(как в TC или FAR). Огромное спасибо. Проблема обнаружена. Буду думать над алгоритмом сортировки.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)