4

我正在尝试实现 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 本身完成,它提供了一种重新排序列表中集合项的方法。我希望通过简单地重新排序现有对象来做到这一点,而无需创建、销毁或分配任何对象。这可能来自 Classes.pas TCollection 的子类吗?(如果没有,我可能必须从源克隆制作自己的 TCollection)

4

3 回答 3

9

根据 VCL 源,您不需要手动执行此操作。只需Index像@Sertac 建议的那样设置属性,它应该可以正常工作。如果您有源代码,请查看TCollectionItem.SetIndex.

于 2011-11-28T18:34:25.443 回答
4

您可以使用类似的东西 - 为集合声明一个虚拟类类型,并使用它来访问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;
于 2011-11-28T18:32:58.100 回答
0

这是一个按 DisplayName 排序的类帮助器解决方案:您可以根据需要改进排序,我使用 TStringList 为我进行排序。类助手在任何你引用包含类助手的单元的地方都可用,所以如果你有一个实用单元把它放在那里。

interface

  TCollectionHelper = class helper for TCollection    
  public    
    procedure SortByDisplayName;    
  end;

Implementation

procedure TCollectionHelper.SortByDisplayName;    
var i, Limit : integer;    
    SL: TStringList;    
begin    
  SL:= TStringList.Create;    
  try    
    for i := self.Count-1 downto 0 do    
      SL.AddObject(Items[i].DisplayName, Pointer(Items[i].ID));    
    SL.Sort;    
    Limit := SL.Count-1;    
    for i := 0 to Limit do    
      self.FindItemID(Integer(SL.Objects[i])).Index := i;    
  finally    
    SL.Free;    
  end;    
end;

然后使用该方法只需假装它是 TCollection 类的方法。这也适用于 TCollection 的任何子类。

MyCollection.SortByDisplayNameMyCollectionItem.Collection.SortByDisplayName

于 2014-10-02T20:56:37.480 回答