如何将MXML子节点放在自定义Flex 4组件中?

W3C*_*der 5 apache-flex mxml custom-component

以下是自定义组件的示例.它只是一个带有标题标签和近距离图像(X)的框:

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

        (INSTANCE MXML)

    </s:VGroup>
    <mx:Image ... />
</mx:Canvas>
Run Code Online (Sandbox Code Playgroud)

在MXML文档中使用组件时,我希望将"(HEADING TEXT)"替换为参数(应该很简单)以及"(INSTANCE MXML)",其中包含多个标签,文本输入,复选框,等等(也许更难).

我找到了这个基于脚本的方法,但如果存在,我想要一个更清晰的编译时解决方案.有什么建议?

Lee*_*Lee 10

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>
Run Code Online (Sandbox Code Playgroud)

这将让你传递headingText像这样:

 <my:MyComponent headingText="Custom Heading Text" />
Run Code Online (Sandbox Code Playgroud)

您可以对要传递的其他简单值采用相同的方法; 只需声明一个公共属性,使其可绑定,然后在您的组件中,使用数据绑定将属性挂钩到其目标(或目标).

您可以对复杂属性(例如INSTANCE MXML)执行相同的操作.当你使用它时,它看起来像这样:

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

有关如何实现此操作的示例,您可以在flex框架中查看组件的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;
Run Code Online (Sandbox Code Playgroud)

[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);
    }
}
Run Code Online (Sandbox Code Playgroud)

所以现在你的组件将有一个名为的属性mxmlContent,你可以使用以下语法从父mxml组件设置:

<my:MyComponent>
   <my:mxmlContent>
       ... (MXML ELEMENTS HERE) ...
   </my:mxmlContent>
</my:MyComponent> 
Run Code Online (Sandbox Code Playgroud)

您可以default property通过应用元数据将新属性添加到组件中:元[DefaultProperty("mxmlContent")]组类.要从mxml执行此操作,只需将元数据定义包装在<fx:Metadata>元素中. 这里以fx:元数据为例.


把所有上面的内容放在一起,你会得到一些你可以使用的东西:

<my:MyComponent headingText="Custom Text Here">
   (CUSTOM MXML CONTENT HERE)
</my:MyComponent>
Run Code Online (Sandbox Code Playgroud)

编辑:我应该在这里做几个笔记:

  1. "光环"组件(如mx:Canvas)不支持addElement()上面使用的,所以你可能想要使用addChild().

  2. 您应该(可能)使用spark组件而不是halo组件.意思是,<s:Group>用作你的基础而不是<mx:Canvas>.如果这样做,那么您的组件将继承上述mxmlContent属性.如果您希望组件具有自己的"内容"属性(甚至是多个内容属性),只需将它们命名为不同的名称即可.


小智 7

这太棒了.感谢您提供此信息.

由于我不需要那么多控制它,我已经简化了这个解决方案.

我们的容器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}" />
Run Code Online (Sandbox Code Playgroud)

用法:

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

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

</myComponents:MyComponent>
Run Code Online (Sandbox Code Playgroud)

希望这有助于任何人.干杯.

  • 如果添加`<fx:Metadata> [DefaultProperty("content")] </ fx:Metadata>`到MyComponent.mxml,则可以在使用该类时删除`<myComponents:content>`标记.往上看. (2认同)