为什么视觉元素不会显示在从另一个自定义组件扩展的自定义组件中

时间:2011-09-06 22:08:37

标签: actionscript-3 flex4 flash-builder mxml custom-component

我创建了一个自定义MXML组件TurboContent,它扩展了NavigatorContent类:

<s:NavigatorContent xmlns:fx="http://ns.adobe.com/mxml/2009"
        xmlns:s="library://ns.adobe.com/flex/spark"
        xmlns:mx="library://ns.adobe.com/flex/mx">

<fx:Metadata>
[DefaultProperty("mxmlContentFactory")]
</Fx:Metadata>

<s:Group id="midWrapper">
    <s:Button id="btnAdd" />
</s:Group>
<s:Group id="rightWrapper" >
    <s:DataGrid id="dgdSelect" >
        <s:columns>
            <s:ArrayList>
                <s:GridColumn headerText="Yo"></s:GridColumn>
            </s:ArrayList>
        </s:columns>
    </s:DataGrid>
    <s:Button id="btnRemove" />
    <s:Button id="btnClear" />
</s:Group>
</s:NavigatorContent>

我正在尝试扩展该自定义组件,但是当我向第二个扩展组件添加显示元素时,它们的元素永远不会被看到。例如:(第一个自定义组件在comp包中)

<comp:TurboContent xmlns:fx="http://ns.adobe.com/mxml/2009"
        xmlns:s="library://ns.adobe.com/flex/spark"
        xmlns:mx="library://ns.adobe.com/flex/mx"
        xmlns:comp="comp.*">

<s:Button id="myButton"/>

</comp:TurboContent>

在这种情况下,'myButton'组件永远不会显示,但基本组件的所有元素都会显示(3个按钮和一个数据网格)。

2 个答案:

答案 0 :(得分:2)

我很想知道你想要达到的目的是什么?

从代码片段来看,您似乎正在尝试构建一个新视图,该视图可视地继承TurboContent组件并向其添加另一个按钮。

真正发生的事情是 NavigatorContent 扩展 SkinnableContainer 。 SkinnableContainer具有默认属性 mxmlContentFactory ,初始化后无法更改或替换,或者在其上添加内容,除非您使用ActionScript执行此操作:

mxmlContentFactory = null; // or some IDeferredInstance

但是,你的视觉继承方法不是视觉继承,而是内容替换。

基类已经初始化了它,因此子类不能对它进行修改。

答案 1 :(得分:1)

据我所知,直接在MXML中定义组件的模式(如您在FIAW系列中所做的那样)不允许在子容器的显示列表中直观地插入子项。其中一个问题是mxmlContent(通常皮肤会控制)是在组件中静态定义的,而且似乎不能直接在MXML组件中使用contentGroup

为了更好地控制,以及我认为更严格的MVC模式实现(Flex 4,作为框架,实现),尝试将您的可视布局分离到MXML外观,并在AS3中定义组件。 / p>

从我对组件的一点点看,我无法真正判断要将组件的哪些属性公开给将要实例化它的容器。我至少会在这里举例说明如何将信息从组件传递到皮肤。

我为MX组件道歉,但我只有Flex 4.1,我想确保程序编译正常。交换火花版本应该不会太难。

示例组件(TurboContentAS.as)

package components {

  import mx.controls.DataGrid;
  import spark.components.NavigatorContent;

  public class TurboContentAS extends NavigatorContent {

    public function TurboContentAS() {
      super();
    }

    // Skin Parts that constitute the necessary parts of the component
    [SkinPart(required="true")]
    public var dgdSelect:DataGrid;  //just an example

    // property you want to expose to the instantiating object
    [Bindable]
    public var firstColumnHeader:String = "default header";

  }
}

示例皮肤(TurboContentSkin.mxml)

<?xml version="1.0" encoding="utf-8"?>
<s:Skin xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark"
        xmlns:mx="library://ns.adobe.com/flex/mx"
        alpha.disabled="0.5" >

    <fx:Metadata>[HostComponent("components.TurboContentAS")]</fx:Metadata>

    <s:states>
        <s:State name="normal" />
        <s:State name="disabled" />
    </s:states>

    <!-- this is where the children that you add later go-->
    <s:Group id="contentGroup" left="0" right="0" top="100" bottom="0" minWidth="0" minHeight="0">
        <s:layout>
            <s:BasicLayout/>
        </s:layout>
    </s:Group>
    <s:Group id="midWrapper">
        <s:Button id="btnAdd" label="Add" />
    </s:Group>
    <s:Group id="rightWrapper" left="200">
        <s:layout>
            <s:VerticalLayout/>
        </s:layout>
        <mx:DataGrid id="dgdSelect">
            <mx:columns>
                <fx:Array>
      <!-- This will bind to the publicly exposed property in the component definition -->
                    <mx:DataGridColumn  headerText="{hostComponent.firstColumnHeader}"/>
                </fx:Array>
            </mx:columns>
        </mx:DataGrid>
        <s:Button id="btnRemove" label="Remove"/>
        <s:Button id="btnClear" label="Clear"/>
    </s:Group>
</s:Skin>

示例实例化

<components:TurboContentAS skinClass="skins.TurboContentSkin" firstColumnHeader="myHeader">
        <s:Button label="myButton"/>
    </components:TurboContentAS>