Отобразить сообщение о том, что список искр пуст - PullRequest
3 голосов
/ 13 июля 2011

Извините, это, вероятно, очень простой вопрос, но как во Flex можно отобразить сообщение в компоненте Spark List, в котором говорится, что список пуст.Например, если у меня есть список, показывающий количество невыполненных заданий, если мой список пуст, то я хочу, чтобы в списке отображалось сообщение о том, что «нет заданий для выполнения».

Я бы предпочел не использовать средство визуализации элементов, потому что тогда это элемент (список не пустой), и элемент можно выбрать.

Кажется, это должно быть очень тривиально, и янадеюсь, что это так.

Заранее спасибо, Фил

Ответы [ 2 ]

6 голосов
/ 13 июля 2011

Вы можете работать с оверлеем, который будет отображаться только в том случае, если у поставщика данных нет элементов, например:

<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 точно так же, как в предыдущем примере.Примените его ко всем компонентам List с помощью CSS:

s|List {
    skinClass: ClassReference("my.custom.skin.ListSkin");
}
0 голосов
/ 13 июля 2011

Вы можете использовать список, который я создал с необходимой функциональностью:

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>

Надеюсь, это поможет!

...