Flex 4 cssラベルを使用してitemrenderを動的に変更


これまでプロジェクトでflexを使ったことがなかったので、今使っているときはよく知っていることが多いので、以下の方法を紹介します.
この問題についても、googleは行ったことがありますが、関連記事は見つかりませんでしたが、異なるitemRendererに対応するために異なるitemRendererが必要なリストごとにlistskinを書くという記事を見つけました.個人的には、これは良い方法ではないと思います.そうすればlistskinを繰り返し使用することはできません.cssでitemRendererを制御する方法を模索しました.
 
style.css
/* CSS file */
@namespace s "library://ns.adobe.com/flex/spark";
@namespace mx "library://ns.adobe.com/flex/mx";

.ListOne{
	skinClass:ClassReference("ListSkinOne");
	itemRender:ClassReference("ItemRenderOne");
}
.ListTwo{
	skinClass:ClassReference("ListSkinOne");
	itemRender:ClassReference("ItemRenderTwo");
}

  
Application.mxml
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
			   xmlns:s="library://ns.adobe.com/flex/spark" 
			   xmlns:mx="library://ns.adobe.com/flex/mx"
			  
			    width="400" height="400">
	<s:layout>
		<s:BasicLayout/>
	</s:layout>
	<fx:Style source="style.css"/>
	<fx:Script>
		<![CDATA[
			import spark.components.DataRenderer;
			import spark.components.supportClasses.ItemRenderer;
		]]>
	</fx:Script>
	<fx:Declarations>
		<!--       (    、   )     -->
	</fx:Declarations>
	<s:HGroup horizontalCenter="0" verticalCenter="0">
	<s:List styleName="ListOne">
		<s:dataProvider>
			<s:ArrayCollection>
				<fx:Object itemRenderOne="itemRenderOne" itemRenderTwo="itemRenderTwo">
					
				</fx:Object>
			</s:ArrayCollection>
		</s:dataProvider>
	</s:List>
	<s:List  styleName="ListTwo">
		<s:dataProvider>
			<s:ArrayCollection>
				<fx:Object itemRenderOne="itemRenderOne" itemRenderTwo="itemRenderTwo">
					
				</fx:Object>
			</s:ArrayCollection>
		</s:dataProvider>
	</s:List>
	</s:HGroup>
</s:Application>

 
ListSkinOne.mxml
<?xml version="1.0" encoding="utf-8"?>

<!--

    ADOBE SYSTEMS INCORPORATED
    Copyright 2008 Adobe Systems Incorporated
    All Rights Reserved.

    NOTICE: Adobe permits you to use, modify, and distribute this file
    in accordance with the terms of the license agreement accompanying it.

-->

<!--- The default skin class for a Spark List component.  

      @see spark.components.List
        
      @langversion 3.0
      @playerversion Flash 10
      @playerversion AIR 1.5
      @productversion Flex 4
-->
<s:SparkSkin xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark"
      xmlns:fb="http://ns.adobe.com/flashbuilder/2009" minWidth="112"
      alpha.disabled="0.5" blendMode="normal"
	  creationComplete="sparkskin1_creationCompleteHandler(event)"
	  > 
    
    <fx:Metadata>
    <![CDATA[ 
        /** 
         * @copy spark.skins.spark.ApplicationSkin#hostComponent
         */
        [HostComponent("spark.components.List")]
    ]]>
    </fx:Metadata> 
    
    <fx:Script fb:purpose="styling">
        /* Define the skin elements that should not be colorized. 
           For list, the skin itself is colorized but the individual parts are not. */
        static private const exclusions:Array = ["scroller", "background"];

        /**
         * @private
         */
        override public function get colorizeExclusions():Array {return exclusions;}
        
        /* Define the content fill items that should be colored by the "contentBackgroundColor" style. */
        static private const contentFill:Array = ["bgFill"];
        
        /**
         * @private
         */
        override public function get contentItems():Array {return contentFill};
        
        /**
         * @private
         */
        override protected function initializationComplete():void
        {
            useChromeColor = true;
            super.initializationComplete();
        }
 
        /**
         * @private
         */
        override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
        {
            if (getStyle("borderVisible") == true)
            {
                border.visible = true;
                background.left = background.top = background.right = background.bottom = 1;
                scroller.minViewportInset = 1;
            }
            else
            {
                border.visible = false;
                background.left = background.top = background.right = background.bottom = 0;
                scroller.minViewportInset = 0;
            }
            
            borderStroke.color = getStyle("borderColor");
            borderStroke.alpha = getStyle("borderAlpha");
            
            super.updateDisplayList(unscaledWidth, unscaledHeight);
        }

    </fx:Script>
    <fx:Script>
		<![CDATA[
			import mx.events.FlexEvent;
			protected function sparkskin1_creationCompleteHandler(event:FlexEvent):void
			{
				var itemRenderClass:Class=hostComponent.getStyle('itemRender')
				if(itemRenderClass&&(!(dataGroup.itemRenderer as itemRenderClass))){
					dataGroup.itemRenderer=new ClassFactory(itemRenderClass);
				}
			}
		]]>
	</fx:Script>
    <s:states>
        <s:State name="normal" />
        <s:State name="disabled" />
    </s:states>
    
    <fx:Declarations>
        <!--- 
              Defines the appearance of the the List's drop indicator.
              To customize the drop indicator appearance, create a custom ListSkin class.
              The List's layout takes care to size and position the dropIndicator.
              The size of the <code>dropIndicator</code> is typically set to the size of the gaps between the items.
              The minimum and maximum settings are typically respected only in the direction
              along the major axis (the gap axis).  For example a VerticalLayout ignores the 
              <code>minWidth</code> and <code>maxWidth</code> settings, 
              but respect <code>minHeight</code> and <code>maxHeight</code>. 
        
              @copy spark.components.List#dropIndicator
        -->
        <fx:Component id="dropIndicator">
            <s:Group minWidth="3" minHeight="3" maxWidth="3" maxHeight="3">
                <s:Rect left="0" right="0" top="0" bottom="0">
                    <s:fill>
                        <!--- Defines the color of the background. -->
                        <s:SolidColor color="0xBBBBBB" />
                    </s:fill>
                    <s:stroke>
                        <s:SolidColorStroke color="0x868686" weight="1"/>
                    </s:stroke>
                </s:Rect>
            </s:Group>
        </fx:Component>
    </fx:Declarations>

    <!-- border -->
    <!--- @private -->
    <s:Rect left="0" right="0" top="0" bottom="0" id="border">
        <s:stroke>
            <!--- @private -->
            <s:SolidColorStroke id="borderStroke" weight="1"/>
        </s:stroke>
    </s:Rect>
    
    <!-- fill -->
    <!--- Defines the background appearance of the list-based component. -->
    <s:Rect id="background" left="1" right="1" top="1" bottom="1" >
        <s:fill>
        <!--- Defines the color of the background. The default color is 0xFFFFFF. -->
            <s:SolidColor id="bgFill" color="0xFFFFFF" />
        </s:fill>
    </s:Rect>

    <!--- The Scroller component to add scroll bars to the list. -->
    <s:Scroller left="0" top="0" right="0" bottom="0" id="scroller" minViewportInset="1" hasFocusableChildren="false">
        <!--- @copy spark.components.SkinnableDataContainer#dataGroup -->
        <s:DataGroup id="dataGroup" itemRenderer="spark.skins.spark.DefaultItemRenderer">
            <s:layout>
                <!--- The default layout is vertical and measures at least for 5 rows.  
                When switching to a different layout, HorizontalLayout for example,
                make sure to adjust the minWidth, minHeihgt sizes of the skin -->
                <s:VerticalLayout gap="0" horizontalAlign="contentJustify" requestedMinRowCount="5" />
            </s:layout>
        </s:DataGroup>
    </s:Scroller>
</s:SparkSkin>

 
ItemRenderOne.mxml
<?xml version="1.0" encoding="utf-8"?>
<s:ItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009" 
				xmlns:s="library://ns.adobe.com/flex/spark" 
				xmlns:mx="library://ns.adobe.com/flex/mx" 
				autoDrawBackground="true">
	
	<s:Label text="{data.itemRenderOne}"/>
	
</s:ItemRenderer>

 
 ItemRenderTwoOne.mxml
<?xml version="1.0" encoding="utf-8"?>
<s:ItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009" 
				xmlns:s="library://ns.adobe.com/flex/spark" 
				xmlns:mx="library://ns.adobe.com/flex/mx" 
				autoDrawBackground="true">
	
	<s:Label text="{data.itemRenderOne}"/>
	
</s:ItemRenderer>

 
もちろん、ボタンクリックやstate変更を実現してitemRendererの変更を制御することもできます.