显示Spark列表为空的消息

时间:2011-07-13 16:27:44

标签: list flex flex4 flex-spark

很抱歉,这可能是一个非常容易回答的问题,但在Flex中如何在Spark List组件中显示一条消息,指出List为空。例如,如果我有一个显示未完成作业数量的列表,如果我的列表为空,那么我希望列表中显示一条消息,指出“没有要执行的作业”。

我宁愿不使用Item Renderer,因为它是一个Item(列表不为空),可以选择该项。

这似乎应该是非常微不足道的,我希望它是。

提前致谢, 菲尔

2 个答案:

答案 0 :(得分:6)

您可以使用仅在数据提供者没有项目时才会显示的叠加层,如下所示:

<s:List dataProvider="{dp}" left="0" right="0" top="0" bottom="0" />

<s:Group id="emptyMsgBox" left="0" right="0" top="0" bottom="0" alpha=".7"
         visible="{!dp.length}" includeInLayout="{!dp.length}">

    <s:Rect left="0" right="0" top="0" bottom="0">
        <s:fill>
            <s:SolidColor color="0x000000" />
        </s:fill>
    </s:Rect>

    <s:Label text="no items in list" color="0xffffff" 
             verticalCenter="0" horizontalCenter="0" />
</s:Group>

你也可以使用状态而不是'visible','includeInLayout'和'dp.length'之间的绑定

修改:如果您希望在所有List组件中都有此行为,则可以为List创建自定义外观,如下所示:

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

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

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

    <s:Rect left="0" right="0" top="0" bottom="0" id="border">
        <s:stroke>
            <s:SolidColorStroke id="borderStroke" weight="1"/>
        </s:stroke>
    </s:Rect>

    <s:Rect id="background" left="1" right="1" top="1" bottom="1" >
        <s:fill>
            <s:SolidColor id="bgFill" color="0xFFFFFF" />
        </s:fill>
    </s:Rect>

    <s:Scroller id="scroller" left="0" top="0" right="0" bottom="0" 
                minViewportInset="1" hasFocusableChildren="false">

        <s:DataGroup id="dataGroup" 
                     itemRenderer="spark.skins.spark.DefaultItemRenderer">
            <s:layout>
                <s:VerticalLayout gap="0" horizontalAlign="contentJustify" 
                                  requestedMinRowCount="5" />
            </s:layout>
        </s:DataGroup>
    </s:Scroller>

    <s:Group id="emptyMsgBox" left="0" right="0" top="0" bottom="0" alpha=".7"
             visible="{!dataGroup.dataProvider.length}" 
             includeInLayout="{!dataGroup.dataProvider.length}">

        <s:Rect left="0" right="0" top="0" bottom="0">
            <s:fill>
                <s:SolidColor color="0x000000" />
            </s:fill>
        </s:Rect>

        <s:Label text="no items in list" color="0xffffff" 
                 verticalCenter="0" horizontalCenter="0" />
    </s:Group>

</s:Skin>

这是皮肤类的精简版本,但总结一下:您所做的就是将叠加组添加到原始Spark ListSkin中,其方式与上一个示例完全相同。 使用CSS将其应用于所有List组件:

s|List {
    skinClass: ClassReference("my.custom.skin.ListSkin");
}

答案 1 :(得分:0)

您可以使用我创建的具有所需功能的列表:

package
{
import flash.events.Event;

import mx.collections.IList;

import spark.components.List;
import spark.components.supportClasses.TextBase;

[SkinState("disabledEmpty")]
[SkinState("normalEmpty")]
public class ListWithMessage extends List
{
    [SkinPart(required = "false")]
    public var emptyMessageLabel:TextBase;

    /**
     * @inheritDoc
     */
    override public function set dataProvider(value:IList):void
    {
        super.dataProvider = value;

        invalidateSkinState();
    }

    //--------------------------------------
    // emptyMessage 
    //--------------------------------------

    private var _emptyMessage:String = "Empty";

    public function get emptyMessage():String
    {
        return _emptyMessage;
    }

    public function set emptyMessage(value:String):void
    {
        if (_emptyMessage == value)
            return;
        _emptyMessage = value;
        invalidateProperties();
    }

    /**
     * @inheritDoc
     */
    override protected function commitProperties():void
    {
        super.commitProperties();

        if (emptyMessageLabel)
            emptyMessageLabel.text = _emptyMessage;
    }

    /**
     * @inheritDoc
     */
    override protected function getCurrentSkinState():String
    {
        var state:String = super.getCurrentSkinState();
        if (isListEmpty())
            state += "Empty";
        return state;
    }

    /**
     * @inheritDoc
     */
    override protected function partAdded(partName:String, instance:Object):void
    {
        super.partAdded(partName, instance);

        if (instance == emptyMessageLabel)
            emptyMessageLabel.text = _emptyMessage;
    }

    private function isListEmpty():Boolean
    {
        return !dataProvider || dataProvider.length == 0;
    }

    /**
     * @inheritDoc
     */
    override protected function dataProvider_collectionChangeHandler(event:Event):void
    {
        super.dataProvider_collectionChangeHandler(event);

        invalidateSkinState();
    }
}
}

此列表的示例外观:

<?xml version="1.0" encoding="utf-8"?>
<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.disabledGroup="0.5" blendMode="normal"> 
    <fx:Metadata>[HostComponent("ListWithMessage")]</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>

    <s:states>
        <s:State name="normal" stateGroups="normalGroup" />
        <s:State name="disabled" stateGroups="disabledGroup" />
        <s:State name="normalEmpty" stateGroups="emptyGroup,normalGroup" />
        <s:State name="disabledEmpty" stateGroups="emptyGroup,disabledGroup" />
    </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:Label id="emptyMessageLabel" fontSize="16" fontWeight="bold" color="#333333" verticalCenter="0" 
        horizontalCenter="0" width="100%" textAlign="center" includeIn="emptyGroup" />
</s:SparkSkin>

使用示例:

<?xml version="1.0" encoding="utf-8"?>
<s:Application minHeight="600" minWidth="955" xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:local="*"
    xmlns:mx="library://ns.adobe.com/flex/mx" xmlns:s="library://ns.adobe.com/flex/spark">

    <fx:Script>
    <![CDATA[
        import mx.collections.ArrayCollection;

        protected function button1_clickHandler(event:MouseEvent):void
        {
            var item:Object = { label: Math.random() };
            if (list.dataProvider)
                list.dataProvider.addItem(item);
            else
            {
                var dp:ArrayCollection = new ArrayCollection();
                dp.addItem(item);
                list.dataProvider = dp;
            }

        }
    ]]>
    </fx:Script>

    <s:VGroup horizontalCenter="0" verticalCenter="0">
        <local:ListWithMessage allowMultipleSelection="false" emptyMessage="Empty List" enabled="{listEnabled.selected}"
            height="400" id="list" skinClass="ListWithMessageSkin" width="400" />
        <s:CheckBox id="listEnabled" selected="true" label="List enabled" />
        <s:Button click="button1_clickHandler(event)" label="Add Item" />
        <s:Button click="list.dataProvider.removeItemAt(list.selectedIndex)" enabled="{list.selectedItem}"
            label="Remove Item" />
    </s:VGroup>
</s:Application>

希望这有帮助!