附加到 mx.controls.PopUpButton 的菜单永远不会改变 [英] Menu attached to mx.controls.PopUpButton never changes

查看:32
本文介绍了附加到 mx.controls.PopUpButton 的菜单永远不会改变的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我准备了一个非常简单的测试用例来演示我的问题.

I have prepared a very simple test case to demo my problem.

请将以下 2 个文件放入 Flash Builder 4.6 项目中,它们将立即运行.

Please just place the 2 files below into a Flash Builder 4.6 project and they will run instantly.

我的问题是附加到我的(稍作修改的)自定义 PopUpButton 的菜单永远不会改变 - 即使当您单击它右侧的 3 个按钮之一时底层 Array 数据提供程序发生了更改:

My problem is that the menu attached to my (slightly modified) custom PopUpButton never changes - even though the underlying Array data provider is changed when you click one of the 3 buttons on the right side of it:

AuxButtonTest.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"
    xmlns:comps="*"
    creationComplete="init()">

    <fx:Script>
        <![CDATA[
            import mx.controls.Alert;
            import mx.events.FlexEvent;

            private const XML1:XML = 
                <pref>
                    <aux event="1">One</aux>
                    <aux event="2">Two</aux>
                    <aux event="3">Three</aux>
                    <aux event="4">Four</aux>
                    <aux event="5">Five</aux>
                </pref>;

            private const XML2:XML = 
                <pref>
                    <aux event="1">One</aux>
                    <aux event="2">Two</aux>
                </pref>;

            private const XML3:XML = 
                <pref>
                    <aux event="3">Three</aux>
                </pref>;

            public function init():void {
                _auxBtn.update(XML1.aux);
            }

            //private function handleAuxChosen(event:PrefEvent):void {
                //Alert.show(event.toString());
            //}
        ]]>
    </fx:Script>

    <s:controlBarContent>
            <!-- commented: aux_chosen="handleAuxChosen(event)" -->
        <comps:AuxButton id="_auxBtn" />
        <s:Button id="_btn1" label="XML 1" click="_auxBtn.update(XML1.aux);" />
        <s:Button id="_btn2" label="XML 2" click="_auxBtn.update(XML2.aux);" />
        <s:Button id="_btn3" label="XML 3" click="_auxBtn.update(XML3.aux);" />
    </s:controlBarContent>
</s:Application>

AuxButton.mxml(我基于 PopUpButton 的自定义组件):

AuxButton.mxml (my custom component based on PopUpButton):

<?xml version="1.0" encoding="utf-8"?>
<mx:PopUpButton
    xmlns:fx="http://ns.adobe.com/mxml/2009" 
    xmlns:s="library://ns.adobe.com/flex/spark" 
    xmlns:mx="library://ns.adobe.com/flex/mx"
    popUp="{_menu}"
    creationComplete="init(event)">

    <fx:Metadata> 
        <!-- [Event(name="aux_chosen", type="PrefEvent")] -->
    </fx:Metadata>

    <fx:Script>
        <![CDATA[
            import mx.controls.Menu;
            import mx.events.MenuEvent;
            import mx.events.FlexEvent;

            private var _str:String;

            [Bindable]
            private var _data:Array = new Array();

            [Bindable]
            private var _menu:Menu = new Menu();

            private function init(event:FlexEvent):void {
                _menu.dataProvider = _data;
                _menu.addEventListener('itemClick', handleMenu);
                addEventListener('click', handleClick);
            }

            public function update(xlist:XMLList):void {
                _data.length = 0;
                for each (var xml:XML in xlist) {
                    _data.push({label: xml, event: xml.@event});
                }

                label = _data[0].label;
                _str = _data[0].event;

                enabled = true;
            }

            private function handleMenu(event:MenuEvent):void {
                label = event.label;
                _str = event.item.event;
            }           

            private function handleClick(event:MouseEvent):void {
                enabled = false;
                //dispatchEvent(new PrefEvent(PrefEvent.AUX_CHOSEN, _str));
            }
        ]]>
    </fx:Script>

</mx:PopUpButton>

我已经注释掉了我的自定义事件 - 这里无关紧要.

I've commented my custom event out - it doesn't matter here.

请点击按钮几次,然后查看菜单 - 它总是有 5 个项目,这是错误的.

Please just click at the buttons few times and then look at the menu - it always has 5 items and that is wrong.

更新:感谢您的回答 - 以下代码现在对我有用.我仍然想知道为什么不支持 ArrayList,但 ArrayCollection 工作正常.

UPDATE: Thank you for the answers - the following code works now for me. I still wonder why isn't ArrayList supported, but ArrayCollection works fine.

AuxButtonText.mxml:

<?xml version="1.0" encoding="utf-8"?>
<mx:PopUpButton
    xmlns:fx="http://ns.adobe.com/mxml/2009" 
    xmlns:s="library://ns.adobe.com/flex/spark" 
    xmlns:mx="library://ns.adobe.com/flex/mx"
    popUp="{_menu}"
    creationComplete="init(event)">

    <fx:Script>
        <![CDATA[
            import mx.controls.*;
            import mx.events.*;
            import mx.collections.*;

            private var _str:String;

            [Bindable]
            private var _data:ArrayCollection = new ArrayCollection();
            //private var _data:ArrayList = new ArrayList();

            [Bindable]
            private var _menu:Menu = new Menu();

            private function init(event:FlexEvent):void {
                _menu.dataProvider = _data;
                _menu.addEventListener('itemClick', handleMenu);
                addEventListener('click', handleClick);
            }

            public function update(xlist:XMLList):void {
                _data.removeAll();

                if (xlist == null || xlist.length() == 0) {
                    enabled = false;
                    return;
                }

                for each (var xml:XML in xlist)
                    _data.addItem({label: xml, event: xml.@event});

                label = _data.getItemAt(0).label;
                _str = _data.getItemAt(0).event;

                enabled = true;
            }

            private function handleMenu(event:MenuEvent):void {
                label = event.label;
                _str = event.item.event;
            }           

            private function handleClick(event:MouseEvent):void {
                enabled = false;
                //dispatchEvent(new PrefEvent(PrefEvent.AUX_CHOSEN, _str));
            }
        ]]>
    </fx:Script>

</mx:PopUpButton>

AuxButton.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"
    xmlns:comps="*"
    initialize="init()">

    <fx:Script>
        <![CDATA[
            private const XML1:XML = 
                <pref>
                    <aux event="1">One</aux>
                    <aux event="2">Two</aux>
                    <aux event="3">Three</aux>
                    <aux event="4">Four</aux>
                    <aux event="5">Five</aux>
                </pref>;

            private const XML2:XML = 
                <pref>
                    <aux event="1">One</aux>
                    <aux event="2">Two</aux>
                </pref>;

            private const XML3:XML = 
                <pref>
                    <aux event="3">Three</aux>
                </pref>;

            private const XML4:XML = 
                <pref>
                </pref>;

            public function init():void {
                _auxBtn.update(XML1.aux);
            }
        ]]>
    </fx:Script>

    <s:controlBarContent>
        <comps:AuxButton id="_auxBtn" />
        <s:Button id="_btn1" label="XML 1" click="_auxBtn.update(XML1.aux);" />
        <s:Button id="_btn2" label="XML 2" click="_auxBtn.update(XML2.aux);" />
        <s:Button id="_btn3" label="XML 3" click="_auxBtn.update(XML3.aux);" />
        <s:Button id="_btn4" label="LEN=0" click="_auxBtn.update(XML4.aux);" />
        <s:Button id="_btn5" label="NULL" click="_auxBtn.update(null);" />
    </s:controlBarContent>
</s:Application>

推荐答案

当数组的内容发生变化时,它不会调度任何事件.根据经验:在数组上使用 [Bindable] 并将其用作某种 dataProvider通常 是一个坏主意,因为添加/删除不会调度任何事件因此不会被任何组件处理.

Arrays do not dispatch any events when their content changes. As a rule of thumb: Using [Bindable] on an Array and using it as some kind of dataProvider is usually a bad idea since adding/removing doesn't dispatch any events and therefore won't be handled by any component.

代替 Array 使用 ArrayCollection ,它会在其内容发生变化时分派 CollectionEvent.COLLECTION_CHANGE 类型的事件.Flex SDK 中的大多数组件都会处理这些事件并相应地更新自身.因此,以下代码有效,因为将新的 source 分配给 ArrayCollection 分派了一个 CollectionEvent 这会导致 Menu更新其菜单项.

Instead of Array use an ArrayCollection which dispatches events of type CollectionEvent.COLLECTION_CHANGE whenever its content changes. Most components in the Flex SDK handle those events and update itself accordingly. So, the following code works since assigning a new source to the ArrayCollection dispatches a CollectionEvent which causes the Menu to update its menu items.

// you don't need [Bindable] on _data
private var _data:ArrayCollection = new ArrayCollection();

public function update(xlist:XMLList):void
{
    var items:Array = [];

    for each (var xml:XML in xlist)
    {
        items.push({label: xml, event: xml.@event});
    }

    _data.source = items;

    if (items.length > 0)
    {
        label = items[0].label;
        _str = items[0].event;
    }

    enabled = true;
}

这篇关于附加到 mx.controls.PopUpButton 的菜单永远不会改变的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆