2.8 动态填充菜单
2.8.1 问题
你想填充并动态改变菜单
2.8.2 解答
用 ActionScript 分配一个 ArrayCollection 或 XMLListCollection 这样的 Collection 对象给 MenuBar 控件的 dataProvider 属性。
2.8.3 讨论
在 Flex 3 里的 MenuBar 控件支持在运行时动态生成菜单项。下面的代码生成一个有 MenuBar 控件的应用,当应用被初始化时,这个 MenuBar 被一个 ArrayCollecton 对象填充。
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" creationComplete="initApp(event)"> <mx:MenuBar id="menu" dataProvider="{menu_dp}"/> <mx:Script> <![CDATA[ import mx.collections.ArrayCollection; import mx.events.FlexEvent; [Bindable] private var menu_dp:ArrayCollection; private function initApp(evt:FlexEvent):void { var temp:Array = new Array(); var subNodes:ArrayCollection = new ArrayCollection([{label:"New"}, {label:"Open"}, {label:"Close",enabled:false}]); temp.push({label:"File",children:subNodes}); temp.push({label:"Edit"}); temp.push({label:"Source"}); subNodes = new ArrayCollection([{label:"50%", type:"radio",roupName:"one"}, {label:"100%", type:"radio", groupName:"one",selected:true}, {label:"150%", type:"radio", groupName:"one"}]); temp.push({label:"View",children:subNodes}); menu_dp = new ArrayCollection(temp); } ]]> </mx:Script> </mx:Application>
上述代码用 binding 绑定一个名为 menu_dp 的 ArrayCollecton 对象到 MenuBar 组件的 dataProvider 属性。在该应用的 creationComplete 事件发生时, menu_dp 被初始化,并填充菜单项。就像 Flex 里的其它数据驱动组件一样,使用类似 ArrayCollection 或 XMLListCollection 的 Collection 组件,可以确保基础数据的任何变化都会导致控件的显示作相应的刷新。
译者注 : 请将 subNodes 的第二项的 selected 属性改成 toggled 。如 2.7 节所述, toggled 属性才是控制 radio 类型的菜单项是否被选中的。
Collection 组件提供了便利的方法编辑,添加,删除菜单项。为了说明这一点,这个例子在 MenuBar 下添加了一个简单的 Form 组件,让你可以根据他们在 ArrayCollecton 里的索引编辑菜单。
<mx:Form> <mx:FormHeading label="Menu Editor"/> <mx:FormItem label="Menu Index"> <mx:TextInput id="menuIdx" restrict="0-9" text="0" width="20"/> </mx:FormItem> <mx:FormItem label="Sub-Menu Index"> <mx:TextInput id="subMenuIdx" restrict="0-9" width="20"/> </mx:FormItem> <mx:FormItem label="Menu Label"> <mx:TextInput id="label_ti"/> </mx:FormItem> <mx:FormItem> <mx:Button label="Edit" click="editMenu()"/> </mx:FormItem> </mx:Form>
这是一个很基础的 Form ,它的 input 控件可以让你指定数组索引,依此来获取一个特定的菜单项。在 menuIdx 文本框里输入 0 ,并保持 subMenuIdx 为空,则指定 File 菜单的顶级。在 menuIdx 文本框里输入 0 ,在 subMenuIdx 里输入 0 ,则指定 New 子菜单项。
当用户单击 Edit 按钮, editMenu 方法就被调用,这个方法用指定的索引来获取某个菜单项的引用并改变它的标签。请看如下代码:
private function editMenu():void { var itemToEdit:Object; try { itemToEdit = menu_dp.getItemAt(int(menuIdx.text)); if(subMenuIdx.text) { itemToEdit = itemToEdit.children.getItemAt(int(subMenuIdx.text)); } itemToEdit.label = label_ti.text; menu_dp.itemUpdated(itemToEdit); } catch(ex:Error){ trace("could not retrieve menu item"); } }
editMenu 里的代码查找输入 menuIdx 和 subMenuIdx 里的值,依此去寻找一个特定的菜单项,然后用 label_ti 里的值去刷新那个菜单项显示的内容。注意:为了改变菜单的显示,与 MenuBar 关联的 dataProvider 被改变了,然后用 ArrayCollecton 的 itemUpdated 方法来请求刷新菜单显示。在类似这个例子的嵌套数据结构中,调用 itemUpdated 来请求显示刷新很重要。否则,基础数据改变了,但是显示仍然是旧的内容。示例代码中用了一个 try…catch 块来为数组界限做一些基础的错误处理。