Как поместить дочерние узлы MXML в пользовательский компонент Flex 4? - PullRequest
5 голосов
/ 27 ноября 2010

Вот пример пользовательского компонента. Это просто коробка с надписью заголовка и близким изображением (X):

<?xml version="1.0"?>
<mx:Canvas ... >
    <s:VGroup>
        <s:Label text="(HEADING TEXT)" ... />

        (INSTANCE MXML)

    </s:VGroup>
    <mx:Image ... />
</mx:Canvas>

При использовании компонента в документе MXML мне бы хотелось, чтобы "(HEADING TEXT)" был заменен параметром (должен быть простым), а также "(INSTANCE MXML)" с несколькими метками, текстовыми вводами флажки и т. д. (может быть, сложнее).

Я нашел этот основанный на сценариях метод , но я бы хотел более чистое время компиляции , если оно существует. Есть предложения?

Ответы [ 2 ]

10 голосов
/ 28 ноября 2010

MyComponent.mxml:

<?xml version="1.0"?>
<mx:Canvas ... >
    <fx:Script>
        [Bindable]
        public var headingText:String = "Default Heading Text";

    </fx:Script>
    <s:VGroup>
        <s:Label text="{headingText}" ... />

        (INSTANCE MXML)

    </s:VGroup>
    <mx:Image ... />
</mx:Canvas>

Это позволит вам передать текст заголовка следующим образом:

 <my:MyComponent headingText="Custom Heading Text" />

Вы можете использовать тот же подход для других простых значений, которые хотите передатьв;просто объявите открытое свойство, сделайте его привязываемым, затем в своем компоненте используйте привязку данных, чтобы привязать свойство к его месту назначения (или пунктам назначения).

Вы можете сделать то же самое для сложных свойств (например, вашего INSTANCE MXML).).Когда вы используете его, это выглядит так:

<my:MyComponent>
  <my:thePropertyName>
     <s:Label text="whatever..." ... />
     <(OTHER MXML CONTENT) />
  </my:thePropertyName>
  <my:someOtherPropertyName>
    ....
  </my:someOtherPropertyName>
</my:MyComponent>

В качестве примера того, как это реализовать, вы можете проверить свойство mxmlContent компонента spark.components.Group в гибкой среде.Источник слишком длинный, чтобы публиковать здесь, и я не могу найти онлайн-ссылку непосредственно на источник;но основная идея заключается в следующем (вы можете сделать все следующее внутри блока <fx:Script> в файле mxml - вам не нужно создавать чистый класс AS для этого):

[1] объявляйте свойство как тип Array с метаданными ArrayElementType, чтобы указать тип, который вы хотите, чтобы массив содержал.

[ArrayElementType("mx.core.IVisualElement")]
public function set mxmlContent(value:Array):void {
    _mxmlContent = value;
}
private var _mxmlContent:Array;

[2] Вам понадобится немного логики, чтобы перебрать массив во время выполнения и добавить содержимое массива в список отображения компонента.Переопределение createChildren является хорошим местом для запуска этого.Нижеследующее свободно вытекает из реализации setMXMLContent() метода искры Group.Он не охватывает все возможные случаи, но поможет вам начать:

override protected function createChildren():void {
    super.createChildren();
    if( _mxmlContent == null ) return;
    for (i = 0; i < _mxmlContent.length; i++) {   
        var elt:IVisualElement = _mxmlContent[i];
        addElement(elt);
    }
}

Так что теперь ваш компонент будет иметь свойство с именем mxmlContent, которое вы можете установить из родительского компонента mxml, используяСинтаксис:

<my:MyComponent>
   <my:mxmlContent>
       ... (MXML ELEMENTS HERE) ...
   </my:mxmlContent>
</my:MyComponent> 

Вы можете создать новое свойство в default property вашего компонента, применив метаданные: [DefaultProperty("mxmlContent")] вашего класса компонента.Чтобы сделать это из mxml, просто оберните определение метаданных в элемент <fx:Metadata>. см. Здесь пример fx: Метаданные .


сложите все вышеперечисленное вместе, и вы получите что-то, что вы можете использовать, как это:

<my:MyComponent headingText="Custom Text Here">
   (CUSTOM MXML CONTENT HERE)
</my:MyComponent>

Редактировать: Я должен сделатьпара замечаний здесь:

  1. Компоненты "Halo" (например, mx:Canvas) не поддерживают addElement(), как указано выше, поэтому вы, вероятно, захотите использовать addChild()вместо.

  2. Вы должны (вероятно) использовать искровые компоненты вместо компонентов гало.То есть, используйте <s:Group> в качестве базы вместо <mx:Canvas>.Если вы сделаете это, ваш компонент унаследует свойство mxmlContent, описанное выше.если вы хотите, чтобы у вашего компонента было собственное свойство «content» (или даже несколько свойств содержимого), просто назовите их как-нибудь иначе.

7 голосов
/ 30 июня 2011

Это потрясающе.Спасибо за эту информацию.

Поскольку мне не нужно было так много контролировать ее, я немного упростил это решение.

Код для нашего контейнера MyComponent.mxml:

<s:Group ... >
<fx:Script>
    <![CDATA[

    [Bindable]
    [ArrayElementType("mx.core.IVisualElement")]
    public var content:Array;

    ]]>
</fx:Script>

<s:Group width="100%" height="100%" mxmlContent="{content}" />

И использование:

<myComponents:MyComponent
    xmlns:myComponents="myComponents.*"
>

    <myComponents:content>
        <s:Label />
        <s:Label />
        <AnythingWeWant...
    </myComponents:content>

</myComponents:MyComponent>

Надеюсь, это кому-нибудь поможет.Приветствия.

...