Borland明显对TCollection的操作粗制滥造!一、在Object TreeView右键点击TCollection对象,Add Item。受不了他们,他们用的是内部的保护方法既不是InsertItem也不是外部的Add方法。捕获不到Add的信息。而用TCollection的属性编辑器是毫无问题的。二、TCollection的属性编辑器的删除,根本没有用Delete方法,他仅仅是把Item给Free掉就完事!TCollection里面的FItems根本没有同步删除不说!根本就没有调用Delete方法。而在Object TreeView右键点击TCollection对象,Edit -> Delete,他们用的也是私有方法RemoveItem。最抓狂的还是我这几天写的连动代码,被我删除全部重写了好几遍。我以为是我的问题,当我用CodeSite跟踪了许多地方,我才发现,是delphi的问题。唉…… 我还是自己写组件编辑器吧。如果大家使用TCollection写组件,最好还是自己写属性编辑器。唉……

解决方案 »

  1.   

    哇靠!还好牛?牛什么?这里会写组件的几乎都会写组件编辑器。本来就是基础……唉,Vcl用到TCollection的地方,无一例外的一般都不需要属性编辑器直接添加删除。以后得注意小心使用了……使用类似TDBGridColumns添加TColumn一定小心了…… 唉……
      

  2.   

    好像TCollection内部根本不关心FItems这个TList对象的操作。为啥?
      

  3.   

    一,不清楚。
    二,仅把ITEM FREE掉的做法是正确的。当调用ITEM FREE后。------------------------------------------
    destructor TCollectionItem.Destroy;
    begin
      SetCollection(nil);//把ITEM自已从LIST中删掉。
      inherited Destroy;
    end;
    ---------------------------------------------
    procedure TCollectionItem.SetCollection(Value: TCollection);
    begin
      if FCollection <> Value then
      begin
        if FCollection <> nil then FCollection.RemoveItem(Self);
        if Value <> nil then Value.InsertItem(Self);
      end;
    end;
      

  4.   

    呵呵,没有好好用过TColection这个东西,当初看了看觉得有点乱
    感觉好像是想实现容器类,但是Pascal又没有泛型,所以就很别扭
      

  5.   

    哦,我没有注意这一点,谢谢哈欠老兄提醒,原来Item是从Collection自己消灭自己。这样做甚好,在析构自己之前,从Owner那里搞掉自己。晓得了,但是Add这个,我在看Sprig的东西,证明我自己使用方面是错的。唉,我很希望我分析的是错的……
      

  6.   

    有关第一个,我找到了操作的代码:procedure TCollectionSprig.AddType(Index: Integer);
    begin
      SelectItems([TCollection(Item).Add]);
    end;就是执行了Add方法,跟踪一下:function TCollection.Add: TCollectionItem;
    begin
      Result := FItemClass.Create(Self);
      Added(Result);
    end;我想哈欠老兄所说的,自己删除自己,难道不添加自己?唉…… 就在上一行:constructor TCollectionItem.Create(Collection: TCollection);
    begin
      SetCollection(Collection);
    end;procedure TCollectionItem.SetCollection(Value: TCollection);
    begin
      if FCollection <> Value then
      begin
        if FCollection <> nil then FCollection.RemoveItem(Self);
        if Value <> nil then Value.InsertItem(Self);
      end;
    end;经过InsertItem,我自然得到cnAdded。但是我没有得到,而是直接得到了一个Item,而且Update方法被执行。我跳出去之后,发现才捕获了cnAdded。我奇怪的是,哪个地方执行了Update呢?Add一定被执行过了,而且是在InsertItem之前。分析InsertItem的代码,procedure TCollection.InsertItem(Item: TCollectionItem);
    begin
      if not (Item is FItemClass) then TList.Error(@SInvalidProperty, 0);
      FItems.Add(Item);
      Item.FCollection := Self;
      Item.FID := FNextID;
      Inc(FNextID);
      SetItemName(Item);
      Notify(Item, cnAdded);
      Changed;
      NotifyDesigner(Self, Item, opInsert);
    end;只有SetItemName才有可能调用Update,跟踪之后果然是我用他调用了Update。欣喜中,自己没有真正了解机理,欣喜TCollection其实没有问题。哈。可以继续写组件了。多谢哈欠老兄点拨。