Как изменить порядок элементов в коллекции TCollection? - PullRequest
4 голосов
/ 28 ноября 2011

Я пытаюсь реализовать методы MoveItemUp и MoveItemDown, которые перемещают выбранную строку вверх или вниз на один индекс в пределах TCollection.

Следующий код, добавленный в мой подкласс TCollection, не работает:

procedure TMyCollection.MoveRowDown(index: Integer);
var
 item:TCollectionItem;
begin
  if index>=Count-1 then exit;
  item := Self.Items[index];
  Self.Delete(index); // whoops this destroys the item above.
  Self.Insert(index+1);
  Self.SetItem(index+1,item); // this actually does an assign from a destroyed object.
end;

Я вполне уверен, что это должно быть возможно во время выполнения, так как это делается во время разработки самой Delphi IDE, которая предоставляет способ переупорядочить элементы Collection в списке.Я надеюсь сделать это, просто переупорядочив существующие объекты, не создавая, не уничтожая и не назначая какие-либо объекты.Возможно ли это из подкласса Classes.pas TCollection?(Если нет, возможно, мне придется сделать свою собственную коллекцию TCollo из исходного клона)

Ответы [ 3 ]

9 голосов
/ 28 ноября 2011

Согласно источнику VCL, вам не нужно делать это вручную.Просто установите свойство Index, как предложено @Sertac, и оно должно работать нормально.Если у вас есть источник, проверьте код TCollectionItem.SetIndex.

4 голосов
/ 28 ноября 2011

Вы можете использовать что-то вроде этого - объявить фиктивный тип класса для коллекции и использовать его для получения доступа к внутреннему FItems этой коллекции, который является TList. Затем вы можете использовать метод TList.Exchange для обработки фактического перемещения (или любой другой функциональности TList, конечно).

type
  {$HINTS OFF}
  TCollectionHack = class(TPersistent)
  private
    FItemClass: TCollectionItemClass;
    FItems: TList;
  end;
  {$HINTS ON}

// In a method of your collection itself (eg., MoveItem or SwapItems or whatever)
var
  TempList: TList;
begin
  TempList := TCollectionHack(Self).FItems;
  TempList.Exchange(Index1, Index2);
end;
0 голосов
/ 03 октября 2014

Вот вспомогательное решение для класса, которое сортирует по DisplayName: Вы можете улучшить сортировку, если хотите, я использовал TStringList для своей сортировки.Помощник класса доступен везде, где вы ссылаетесь на модуль, содержащий помощник класса, поэтому, если у вас есть служебный модуль, поместите его туда.метод класса TCollection.Это работает и для любого подкласса TCollection.

MyCollection.SortByDisplayName или MyCollectionItem.Collection.SortByDisplayName.

...