2010-11-27 9 views
5

Aquí hay un ejemplo de un componente personalizado. Es sólo una caja con una etiqueta de título y una imagen de primer (X):¿Cómo poner nodos secundarios MXML dentro de un componente Flex 4 personalizado?

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

     (INSTANCE MXML) 

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

Cuando se utiliza el componente en un documento MXML, me gustaría tener el "(TEXTO DE ENCABEZAMIENTO)" sustituye con un parámetro (debería ser fácil) así como el "(INSTANCE MXML)" con varias etiquetas, entradas de texto, casillas de verificación, etc. (quizás más difícil).

He encontrado this script-based method, pero me gustaría tener un limpiador en tiempo de compilación solución, si existe. ¿Alguna sugerencia?

Respuesta

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> 

que le permitirá pase en el HeadingText así:

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

se puede seguir el mismo enfoque para otros valores simples que desea pasar en; solo declare una propiedad pública, hágalo enlazable, luego dentro de su componente, use el enlace de datos para enlazar la propiedad a su destino (o destinos).

Puede hacer lo mismo para propiedades complejas (como su INSTANCE MXML). Parece que este, cuando lo utiliza:

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

Para un ejemplo de cómo implementar esto, usted puede comprobar fuera de la propiedad mxmlContent del componente spark.components.Group en el marco de la flexión. La fuente es demasiado larga para publicar aquí, y parece que no puedo encontrar un enlace en línea directamente a la fuente; pero la idea básica es la siguiente (se puede hacer todo lo siguiente dentro de un bloque <fx:Script> en un archivo MXML - que no tiene que hacer una pura AS clase con el fin de hacer esto):

[1] declarar la propiedad como tipo Array, con los metadatos ArrayElementType para indicar el tipo que desea que contenga la matriz.

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

[2] que necesitará un poco de lógica en bucle sobre la matriz en tiempo de ejecución, y añadir el contenido de la matriz a la lista de visualización del componente. La anulación createChildren es un buen lugar para activar esto. Lo siguiente se deriva libremente de la implementación del método setMXMLContent() de la chispa Group. No cubre todos los casos posibles, sino que va a empezar:

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); 
    } 
} 

Así que ahora su componente tendría una propiedad llamada mxmlContent, que podría establecer desde un componente mxml matriz utilizando la sintaxis:

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

Puede hacer su nueva propiedad en el default property de su componente, aplicando los metadatos: [DefaultProperty("mxmlContent")] su clase de componente. Para hacer esto desde mxml, simplemente ajuste la definición de metadatos en un elemento <fx:Metadata>. see here for example of fx:Metadata.


poner todas las juntas por encima, y ​​obtendrá algo que se puede utilizar de esta manera:

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

Editar: que debería hacer un par de notas aquí:

  1. "Halo" componentes (como mx:Canvas) no son compatibles con addElement() como se utilizó anteriormente, por lo que es probable que desee utilizar addChild() en su lugar.

  2. Debería (probablemente) utilizar componentes de chispa en lugar de componentes de halo. Es decir, use <s:Group> como su base en lugar de <mx:Canvas>. Si hace esto, su componente heredará la propiedad mxmlContent descrita anteriormente. si desea que su componente tenga su propia propiedad de "contenido" (o incluso múltiples propiedades de contenido), simplemente asómbreles algo diferente.

+0

Bueno, no es exactamente una solución * en tiempo de compilación *, pero tal vez no se pueda evitar el procesamiento en tiempo de ejecución. Ciertamente mereces muchas gracias y dado que nadie más se ha acercado, aceptaré esta respuesta. – W3Coder

+0

@ W3Coder: gracias por aceptar. Sé que quería una solución en tiempo de compilación, pero -similar de construir su propio generador de código- simplemente no hay forma de llegar allí. Sin embargo, lo que vale la pena: este es el mismo enfoque utilizado por el marco flexible para tratar el contenido infantil, por lo que sus componentes, escritos de esta manera, deberían ser tan eficientes como cualquier solución en tiempo de compilación. ¡buena suerte! por favor regrese y avísenos si encuentra soluciones diferentes/mejores. – Lee

7

Esto es impresionante. Gracias por esta información

Como no necesitaba tanto control sobre él, simplifiqué un poco esta solución.

Código

para nuestra MyComponent.mxml contenedor:

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

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

    ]]> 
</fx:Script> 

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

y uso:

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

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

</myComponents:MyComponent> 

Espero que esto ayude a nadie. Saludos.

+1

Gran publicación. ¡Justo lo que necesitaba! Kamil, gracias por publicar tu código ... es muy simple de esa manera. – Ofir

+2

Si agrega ' [DefaultProperty (" content ")]' a MyComponent.mxml, puede eliminar las etiquetas '' cuando use la clase. Véase más arriba. – Stephenr

Cuestiones relacionadas