Является ли это возможным? Потомок TCollection для реализации хранения контейнеров TPanel с произвольным содержимым - PullRequest
1 голос
/ 27 сентября 2010

Я новичок в разработке компонентов в Delphi, поэтому хочу знать, возможно ли вообще реализовать мою задачу.

Мне нужно создать визуальный компонент (пользовательский элемент управления) на основе TScrollBox, которыйбудет представлять собой группу TPanel, все эти панели будут выровнены как "Top" внутри этого TScrollBox и могут иметь различную высоту.Он должен действовать как TCollection (добавлять, удалять, переупорядочивать) и должен позволять пользователям добавлять другие элементы управления в эти панели во время разработки.

Я создал эти классы для компонента:

type
  TPanelsGrid = class;

  TPanelsGridItem = class(TCollectionItem)
  private
    FPanel: TPanel;
    procedure SetPanel(Value: TPanel);
    function GetGrid: TPanelsGrid;
  protected
    function GetDisplayName: string; override;
  public
    constructor Create(Collection: TCollection); override;
    destructor Destroy; override;
    procedure Assign(Source: TPersistent); override;
  published
    // This is my TPanel object that should be used at designtime
    // I thought "stored True" will serialize it automatically but I was wrong
    property Panel: TPanel read FPanel write SetPanel stored True; 
  end;

  TPanelsGridItems = class(TCollection)
  private
    FPanelsGrid: TPanelsGrid;
  protected
    function GetItem(Index: Integer): TPanelsGridItem;
    procedure SetItem(Index: Integer; Value: TPanelsGridItem);

    function GetOwner: TPersistent; override;
    procedure Update(Item: TCollectionItem); override;
  public
    property EditorsGrid: TPanelsGrid read FPanelsGrid;
    property Items[Index: Integer]: TPanelsGridItem
      read GetItem write SetItem; default;

    constructor Create(PanelsGrid: TPanelsGrid);
    function Add: TPanelsGridItem;
    procedure Delete(Index: Integer);
  end;

  TPanelsGrid = class(TScrollBox)
  private
    FItems: TPanelsGridItems;
    procedure SetItems(Value: TPanelsGridItems);
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
  published
    property Items: TPanelsGridItems read FItems write SetItems;
  end;

Этот компонент работает нормально во время разработки, я могу добавлять или удалять панели в стеке, когда я отбрасываю некоторый элемент управления (например,TCheckbox) на любой панели, он отображается как «принадлежащий этой панели»: например, я не могу перетащить этот флажок из панели.

Но этот флажок не сохраняется в DFM-файле и не отображается в окне «Структура».

Я предполагаю, что должна быть некоторая ручная сериализация-десериализация контента TPanel, но я понятия не имею, как это сделать.Не могу найти ни одного примера в интернете.Пожалуйста, дайте мне некоторое руководство, если такая реализация вообще возможна.

Добавление :

Так выглядит мой фрагмент DFM-файла после добавления 3 панелей в сетку.:

  object PanelsGrid1 : TPanelsGrid 
    Left = 8
    Top = 8
    Width = 536
    Height = 382
    Anchors = [akLeft, akTop, akRight, akBottom]
    TabOrder = 0
    Items = <
      item
      end
      item
      end
      item
      end>
  end

Как видите, все предметы пусты, но я поставил там флажок и кнопку с переключателем в элементе № 3.

Ответы [ 3 ]

1 голос
/ 30 сентября 2010

В конце концов я решил отказаться от использования TCollection, потому что во время тестирования метода DefineProperties у меня был постоянный сбой IDE.Я думаю, что TCollection просто не был предназначен для такой задачи.

Я нашел соответствующую реализацию внутри источников Delphi внутри элемента управления ExtCtrls.TCustomCategoryPanelGroup.Он поддерживает стек панелей, которые могут быть добавлены или удалены как во время разработки, так и во время выполнения.Я создал свои собственные классы, используя исходный код TCustomCategoryPanelGroup и TCustomCategoryPanel, и он работает, как я хочу.

0 голосов
/ 28 сентября 2010

Убедитесь, что у ваших дочерних панелей есть имена. Вы можете переопределить TCollection.Notify, и если Action - cnAdded, убедитесь, что у панели есть имя.

0 голосов
/ 27 сентября 2010

Думаю, вы можете взглянуть на Элемент управления TMS Poly List

Компоненты TMS Advanced Poly List предлагают чрезвычайно универсальную и гибкую архитектуру для создания практически любых возможных списков элементов.в пользовательских интерфейсах.Обычно это видно, но не ограничивается новым меню приложения Office 2010.В отличие от большинства элементов управления списком пользовательских интерфейсов, где список состоит из элементов одного типа или набора элементов одного типа, компоненты TMS Advanced Poly List могут содержать полиморфные элементы.Все элементы просто должны происходить из базового класса TCustomItem, и любые унаследованные элементы могут быть добавлены.Компоненты TMS Advanced Poly List поставляются с большим набором предварительно созданных элементов списка, но пользовательские классы элементов могут быть добавлены либо по убыванию базового класса TCustomItem, либо любым из уже предоставленных классов.Есть классы элементов для отображения в виде элемента списка, текстовый элемент с форматированием HTML, текстовый элемент с кнопками, элемент с поведением раскрытия / свертывания, элемент с изображением и многое другое.Элементы могут быть добавлены в списки полиморфов либо во время разработки, с богатым редактором времени разработки и во время выполнения с помощью кода.

...