Перейти к содержанию
Fire Monkey от А до Я
  • 0

Сортировка TListViewItems


xenon54

Вопрос

Всем привет! У компонента TListView есть метод sort параметром которого является "TFmxObjectSortCompare".  

TFmxObjectSortCompare = reference to function (Left, Right: TFmxObject): Integer;

Для листбокса сортировка выглядела бы так: 

function TForm1.SortASCII(Left, Right: TFMXObject): Integer;
begin
  Result := CompareText((Left as TListBoxItem ).text (Right as TListBoxItem).Text);

end;

Но в ListView итемы не являются наследниками TFMXObject. И как быть в этой ситуации? Метод сорт получается лишний в TListView или можно как-то по-другому реализовать сортировку?

Ссылка на комментарий

Рекомендуемые сообщения

  • 0
 TListView(Sender).Items.ActiveItems.Sort(
      TComparer<TListViewItem>.Construct(
        function(const Left, Right: TListViewItem): Integer
        var
.......
 
TListView(Sender).Items.Changed;
 
 
p.s. ActiveItems и Changed - это хелперы к соотв-им полям\методам strict private
 
p.s. метод Sort - я вообще не понимаю {censored} он тут нужен. он сортирует свои внутренние объекты стиля
Ссылка на комментарий
  • 0

Узнал про существование хелперов из твоего поста. Погуглил, оказалась клевая штука, плохо что не знал раньше про них :)

В итоге написал следующее:

TObjectHelper = class helper for TListViewItems
    public type
    TItemsList = TList<TListViewItem>;
    public
    procedure MyChanged;
    function MyActiveitems : TItemslist;
  end;

....

implementation

procedure TForm1.Button2Click(Sender: TObject);
begin


  ListView1.Items.MyActiveitems.Sort(
      TComparer<TListViewItem>.Construct(
        function(const Left, Right: TListViewItem): Integer
        begin
          Result := CompareText(Left.text, Right.Text);
        end));

  ListView1.Items.MyChanged;

end;




{ TObjectHelper }

function TObjectHelper.MyActiveitems: TItemslist;
begin
  result := self.FActiveItems;
end;

procedure TObjectHelper.MyChanged;
begin
  self.changed;
end;

Все замечательно работает :)

Спасибо.

Ссылка на комментарий
  • 0

да не за что. для себя я завел привычку обзывать хелперы TListViewItems_helper.

без хелперов работать с фаирманками нельзя....

и вообще, они оч помогают править эмбаркадеровские {censored} "фичи".

без них я бы либо от злости уже стал дурачком, либо кинул все это..

Ссылка на комментарий
  • 0

Что то я не понял в чем проблема у автора. 

Стандартный метод сортировки работает (Delphi Berlin).

 

uses System.Generics.Defaults;
...
procedure TForm1.ButtonSortClick(Sender: TObject);
var
  Comparer: IComparer<TListViewItem>;
begin
  Comparer := TDelegatedComparer<TListViewItem>.Create(
    function(const LeftItm, RightItm: TListViewItem): Integer
    begin
      Result := CompareText(LeftItm.Text, RightItm.Text);
    end);

  ListView1.Items.Sort(Comparer);
end;

А также можно по Data 

 

procedure TForm1.ButtonSortClick(Sender: TObject);
var
  Comparer: IComparer<TListViewItem>;
begin
  Comparer := TDelegatedComparer<TListViewItem>.Create(
    function(const LeftItm, RightItm: TListViewItem): Integer
    begin
       Result := 0; //no change
       if LeftItm.Data['number'] > RightItm.Data['number'] then 
          Result := 1 //depend on sort order asc/desc
       else if LeftItm.Data['number'] < RightItm.Data['number'] then 
          Result := -1; //depend on sort order asc/desc
    end);
 
  ListView1.Items.Sort(Comparer);
end;

 

Не забудьте BeginUpdate - EndUpdate. 

Напомню что к объектам ListViewItem можно обращаться не через Data['name'], а напрямую через индексы, что гораздо быстрее, т.к. не нужно сравнивать все строки в цикле, это важно при большом количестве Objects per Item (напр. больше 5 в режиме DynamicAppearance).

Изменено пользователем ENERGY
Ссылка на комментарий
  • 0

а не подскажите, как тоже самое сделать для scrollbox?

там тоже есть метод Form1.RoomsScrollBox.Content.Sort();

Только у меня ругается на TListViewItem, говорит не знает такого

var
  Comparer: IComparer<TListViewItem>;
Ссылка на комментарий
  • 0
procedure TForm1.SortGroup;
var
  Comparer: IComparer<TEssence>;
begin
 Comparer := TDelegatedComparer<TEssence>.Create(
    function(const LeftItm, RightItm: TEssence): Integer
    begin
      if LeftItm.SortIndex > RightItm.SortIndex then
       Result:= 1
      else if LeftItm.SortIndex < RightItm.SortIndex then
       Result:= -1;
    end);

 Form1.RoomsScrollBox.Content.Sort(Comparer);
end;

Вот так ругается

[dcc32 Error] main_unit.pas(3918): E2010 Incompatible types: 'TFmxObjectSortCompare' and 'System.Generics.Defaults.IComparer<Essenses_unit.TEssence>'

TEssence - мой класс, наследован от TRectangle

Изменено пользователем gonzales
Ссылка на комментарий
  • 0

Вот так компилится

procedure TForm1.SortGroup;
var
  Comparer: IComparer<TFmxObject>;
  t: TFMXObjectSortCompare;
begin
  t := function (LeftItm, RightItm: TFmxObject): integer
      begin
        if TEssence(LeftItm).SortIndex > TEssence(RightItm).SortIndex then
          Result := 1
        else if TEssence(LeftItm).SortIndex < TEssence(RightItm).SortIndex then
          Result := -1;
    end;
  Form1.RoomsScrollBox.sort(t);
end;

но входит в бесконечный цикл

Ссылка на комментарий
  • 0

кривое тз всегда дает еще более кривое решение

сортировать надо данные, а не компоненты на экране

отсортировать список - доли секунды, вывести его на экран - тоже

а вот работать с неповоротливыми экранными компонентами это ну никак не быстро

 

Ссылка на комментарий
  • 0
В 06.06.2020 в 10:32, krapotkin сказал:

сортировать надо данные, а не компоненты на экране

если бы все было так просто...

в моем случае TEssense - это родительский класс для других компонентов, сортировать на этапе создания - означало бы иметь кучу вложенных циклов, не уверен, что это было бы шустро.

А ларчик просто открывался, по недогляду забыл про Result:=0;

Вот рабочий код

procedure TForm1.SortGroup;
begin
  Form1.RoomsScrollBox.sort(
  function(LeftItm, RightItm: TFmxObject): integer
    begin
      Result := 0;
      if TEssence(LeftItm).SortIndex > TEssence(RightItm).SortIndex then
        Result := 1
      else if TEssence(LeftItm).SortIndex < TEssence(RightItm).SortIndex then
        Result := -1;
    end);
end;

Не забываем про BeginUpdate, EndUpdate

Ссылка на комментарий
  • 0

так вот речь и идет о том, что компоненты должны быть отдельно, а данные отдельно

если мы под компонентами понимаем одно и то же - экранные компоненты, предназначенные для отображения данных человеку

программа не человек, ей компоненты побоку, ей бы переменные, классы, списки. 

ну и по коду - ошибка - обращение к переменной form1 внутри метода класса TForm1

Ссылка на комментарий

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить на вопрос...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

  • Последние посетители   0 пользователей онлайн

    • Ни одного зарегистрированного пользователя не просматривает данную страницу
×
×
  • Создать...