我正在尝试实现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的子类中是可能的吗?(如果没有,我可能不得不从源克隆制作自己的TCollection )
发布于 2011-11-29 02:34:25
根据VCL源代码,您不需要手动执行此操作。只需像@Sertac建议的那样设置Index属性,它就会工作得很好。如果您有源代码,请查看TCollectionItem.SetIndex的代码。
发布于 2011-11-29 02:32:58
您可以使用这样的方法--为一个集合声明一个伪类类型,并使用它来访问该集合的内部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;发布于 2014-10-03 04:56:37
这里是一个按DisplayName排序的类帮助器解决方案:如果你喜欢,你可以改进排序,我用了一个TStringList来帮我排序。Class helper在您引用包含类helper的单元的任何地方都可用,所以如果您有一个实用单元,请将它放在那里。
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.SortByDisplayName或MyCollectionItem.Collection.SortByDisplayName。
https://stackoverflow.com/questions/8300399
复制相似问题