数据集
包含一组数据元素的对象就叫做数据集DataSet
如:Array、XMLList、ArrayCollection、XMLListCollection
如何显示一个数据集?
通过labelField指定列表应该显示数据集中哪个属性(局限:只能显示文本)
如果要显示格式化的数据,或者拼接多个属性,则需要使用LabelFunction
如何操作(增删改查)一个数据集?
IViewCursor
如何循环一个数据集?
for循环 for each循环
-----------------------------------------------
List与DataProvider组件
List类与DataGroup类相似,都有一个可以用来设置其数据集的dataProvider
并基于itemRenderer来呈现数据集中的每一项数据!!!
注意:List还有另一个功能,可以管理用户选择的数据项,并可以获取到哪些项被选中(基于这些选中项dosomething)
在List中使用labelFunction属性
labelFunction指定一个函数,该函数会返回一个String
即:通过该函数实现如何显示List中的每一项
在DataGroup中应用itemRenderer
系统提供了DefaultItemRenderer,将使用Label组件呈现每个数据项
创建自定义的itemRenderer
创建itemRenderer时,新类可以实现IDataRenderer接口,也可以继承某个实现了该接口的类
IDataRenderer接口指定了实现它的类必须有实现针对data属性的get和set函数(data通常为Object类型)
itemRenderer的原理:
针对dataProvider中的每一个数据项都创建一个呈现器实例,然后取得相应数据项的数据放到data中
!
应用程序中复写data的set方法,然后将传入的value赋值给我们自己创建的那个引用,这样就获取到
需要的数据了!
虚拟化与List
虚拟化:只创建对用户可见的元素的对象。离开用户可见范围的对象将被回收,然后将原有空间设置为显示新入屏
幕的元素。(好处:只创建用户可见的,不可见的马上回收,节省资源消耗)
如:DataGroup中包含1000个商品,每次显示10个,那么应用程序每次就只创建对用户可见的那10个商品实例
使用方法:
<s:layout>下的布局对象中设置useVirtalLayout="true"
对于List而言,虚拟化是默认开启的!
而且List列表还支持选择功能:
列表项用户呈现一些项,用户选择,列表围绕被选择项提供了很多操作
如:属性、方法、事件
selectedIndex、selectedItem属性可以指定或者取得当前选中的项
--------------------------------------------------------------------创建一个呈现器,在应用程序顶部的控制条中通过呈现器来显示不同商品类别
根据选择的类别显示商品(实现筛选功能)
1.使用List存放控制条中显示的商品种类
2.使用itemRenderer属性指定一个自定义的项目呈现器进行自定义的格式显示
3.因为List还支持事件、属性等,所以可以对列表中选中商品的变化作出响应
主程序:FlexGrocery.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"
creationComplete="handleCreationComplete(event)" xmlns:views="views.*" xmlns:services="services.*">
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
<!-- 将HTTPService获取数据的功能放到两个ActionScript类中进行处理,此处引入即可 -->
<!-- 提供商品类别服务的组件(不可见组件)-->
<services:CategoryService id="categoryService"/>
<!-- 提供具体各种商品服务的组件(不可见组件)-->
<services:ProductService id="productService"/>
</fx:Declarations>
<fx:Script>
<![CDATA[
import mx.events.FlexEvent;
import spark.events.IndexChangeEvent;
//当系统组件构建完成后,会调用到此方法,在这里向远端发起请求,获取数据
//当数据获取成功后,事件监听器会调用指定的方法处理数据
private function handleCreationComplete(event:FlexEvent):void {
categoryService.send();
productService.send();
}
//查看当前购物车中的商品
private function handleViewCartClick( event:MouseEvent ):void {
bodyGroup.currentState="cartView";//切换到bodyGroup下的cartView状态
}
//响应列表的变化,对change事件进行处理
protected function list1_changeHandler(event:IndexChangeEvent):void
{
//当控制条中商品的选中状态改变了,会触发change事件,该方法就会得到执行
//传入当前选中商品的catID,然后products集合会根据此id寻找对应的项,并只呈现匹配的哪些项
productService.filterCollection(event.target.selectedItem.categoryID);
}
]]>
</fx:Script>
<!-- 控制条布局 -->
<s:controlBarLayout>
<s:BasicLayout/>
</s:controlBarLayout>
<!-- 控制条 -->
<s:controlBarContent>
<s:Button y="10" label="Checkout" id="btnCheckout" right="10"/>
<s:Button y="10" label="View Cart" id="btnCartView" right="90" click="handleViewCartClick( event )"/>
<s:Button label="Flex Grocer" x="5" y="5"/>
<!-- 从categoryService中获取商品种类信息 ,使用指定的项目呈现器NavigationItem显示内容-->
<s:List left="200" height="52"
dataProvider="{categoryService.categories}"
itemRenderer="components.NavigationItem"
change="list1_changeHandler(event)">
<s:layout>
<s:HorizontalLayout/>
</s:layout>
</s:List> </s:controlBarContent>
<!-- 实例化商品组件(该组件被单独抽取出来,在主应用程序中实例化) -->
<!-- 从productService中获取商品 -->
<views:ShoppingView id="bodyGroup" width="100%" height="100%" groceryInventory="{productService.products}"/>
<!-- 版权说明 -->
<s:Label text="(c) 2009, FlexGrocer" right="10" bottom="10"/>
</s:Application>
项目呈现器NavigationItem.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">
<s:layout>
<s:VerticalLayout horizontalAlign="center"/>
</s:layout>
<fx:Declarations>
<!-- 将非可视元素(例如服务、值对象)放在此处 -->
</fx:Declarations>
<!-- flex会将针对dataProvider中每项创建对应的呈现器实例,然后将取得的相应数据放到data中-->
<s:Image source="assets/nav_{data.name.toLowerCase()}.jpg"
height="31" width="93"/>
<s:Label text="{data.name}"/>
</s:ItemRenderer>
ProductService.as
对集合中的商品进行过滤,只显示被选择的那类商品
package services
{
import mx.collections.ArrayCollection;
import mx.rpc.events.ResultEvent;
import mx.rpc.http.mxml.HTTPService;
import valueObjects.Product;
/**
* 该类用于获取所有的商品
* 对外提供products(products为ArrayCollection,存放着所有商品)
* @author lenovo
*
*/
public class ProductService extends HTTPService
{
[Bindable]
public var products:ArrayCollection;//获取远程数据,使用e4x找出product节点,转换为对象,放入Array,最后将Array放入ArrayCollection
public function ProductService(rootURL:String=null, destination:String=null)
{
super(rootURL, destination);
this.resultFormat = "e4x";//指定返回xml格式的数据以便使用e4x表达式对xml进行操作
this.url = "http://www.flexgrocer.com/categorizedProducts.xml";//数据源
this.addEventListener(ResultEvent.RESULT,handleProductResult);//事件监听器,并指定事件处理函数
}
private function handleProductResult( event:ResultEvent ):void {
var productArray:Array = new Array();
var resultData:XMLList = event.result..product;//e4x筛选子节点
for each (var p:XML in resultData) {
var product:Product = Product.buildProductFromAttributes( p );//将每个子节点创建对应的product对象
productArray.push( product );//添加到数组中
}
products = new ArrayCollection( productArray );//将整个数组放入ArrayCollection中,为数组提供代理
//为products集合(ArrayCollection)指定一个筛选函数
products.filterFunction = filterForCategory;
products.refresh();//刷新集合
}
//默认选择index=1的商品
private var selectedCategory:Number=1;
//products集合的过滤函数
public function filterForCategory(item:Product) :Boolean {
return item.catID == selectedCategory;//将集合中的每项的catID与selectedCategory进行比较,结果为true的那项将被呈现
}
//当选择其它商品时发生change事件,会将其catID传入到此方法,然后赋值给selectedCategory
//调用集合的refresh方法,重新对集合进行过滤,过滤的时候使用的selectedCategory就是刚才传入的catID
public function filterCollection(id:Number):void {
selectedCategory = id;
products.refresh();
}
}
}
====================================================================
对bodyGroup中的商品进行呈现
1.使用DataGroup
2.使用DataRenderer
ShoppingView.mxml
<?xml version="1.0" encoding="utf-8"?>
<s:Group 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="0" height="0" xmlns:components="components.*">
<s:layout>
<s:HorizontalLayout/>
</s:layout>
<s:states>
<s:State name="State1"/>
<s:State name="cartView"/>
</s:states>
<fx:Script>
<![CDATA[
import cart.ShoppingCart;
import cart.ShoppingCartItem;
import components.ProductItem;
import mx.collections.ArrayCollection;
import valueObjects.Product;
[Bindable]
public var shoppingCart:ShoppingCart = new ShoppingCart();//创建一个购物车,分别传入不同的商品对象中,而不是在每种商品中都new一个购物车!
[Bindable]
public var groceryInventory:ArrayCollection;//用于存放HTTPService返回的各种商品信息
//查看当前购物车中的商品
private function handleViewCartClick( event:MouseEvent ):void {
this.currentState="cartView";
}
//该方法返回一个字符串,用来作为数据集的呈现方式,由labelFunction函数指定
//当List中使用labelFunction时,会自动以正确的方式从dataProvider中获取数据并传递到该方法中
//返回的字符串将作为被呈现的内容
private function renderProductName(item:ShoppingCartItem):String {
var product:Product = item.product;
return "("+item.quantity+")" + product.prodName + " $" + item.subtotal;
}
]]>
</fx:Script>
<fx:Declarations>
<!-- 将非可视元素(例如服务、值对象)放在此处 -->
</fx:Declarations>
<!-- 必须为组件指定在界面中占据的空间大小 否则不可见-->
<s:DataGroup width="100%" height="100%"
width.cartView="0" height.cartView="0" visible.cartView="false"
dataProvider="{groceryInventory}"
itemRenderer="components.ProductItem">
<!-- dataProvider属性指定数据来源,itemRenderer属性负责数据呈现 -->
<!-- 将ProductItem改为了一个DataRenderer-->
<!-- 为DataGroup指定布局对象,否则展现出来的视图都重叠在一起了 -->
<s:layout>
<s:VerticalLayout/>
</s:layout>
</s:DataGroup>
<!-- 购物车组件 -->
<s:VGroup id="cartGroup" height="100%" width.cartView="100%">
<s:List id="cartList"
dataProvider="{shoppingCart.items}" includeIn="State1"
labelFunction="renderProductName"/>
<s:Label text="Your Cart Total: $"/>
<s:Button label="View Cart" click="handleViewCartClick( event )" includeIn="State1"/>
<mx:DataGrid includeIn="cartView" id="dgCart" width="100%">
<mx:columns>
<mx:DataGridColumn headerText="Column 1" dataField="col1"/>
<mx:DataGridColumn headerText="Column 2" dataField="col2"/>
<mx:DataGridColumn headerText="Column 3" dataField="col3"/>
</mx:columns>
</mx:DataGrid>
<s:Button includeIn="cartView" label="Continue Shopping" click="this.currentState=''"/>
</s:VGroup>
</s:Group>
ProductItem.mxml
<?xml version="1.0" encoding="utf-8"?>
<s:DataRenderer 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="100%">
<s:states>
<s:State name="State1"/>
<s:State name="expanded"/>
</s:states>
<fx:Script>
<![CDATA[
import cart.ShoppingCart;
import cart.ShoppingCartItem;
import valueObjects.Product;
[Bindable]
public var product:Product;//由flex在为data赋值的时候,将value赋值给product
public var shoppingCart:ShoppingCart;//购物车从哪里传入呢?
//添加某类商品到购物车,一次添加1个
private function addToCart(product:Product):void {
var sci:ShoppingCartItem = new ShoppingCartItem( product );
shoppingCart.addItem( sci );
}
//从购物车中删除该类商品,一次性全部删除
private function removeFromCart( product:Product ):void {
var sci:ShoppingCartItem = new ShoppingCartItem( product );
shoppingCart.removeItem( sci );
}
//当指定了dataProvider之后,flex会针对数据集中每个数据项创建一个呈现器实例
//然后将取得的数据放到data中保存
//这里覆盖data的set方法,利用上述原理,在赋值时直接将数据赋值到product对象中,而不是赋值给data
public override function set data(value:Object) :void {
this.product = value as Product; //注意进行类型转换
}
]]>
</fx:Script>
<fx:Declarations>
<!-- 将非可视元素(例如服务、值对象)放在此处 -->
</fx:Declarations>
<!-- 商品 -->
<s:VGroup id="products">
<s:Label text="{product.prodName}" id="prodName"/>
<mx:Image source="assets/{product.imageName}" scaleContent="true"
mouseOver="this.currentState='expanded'"
mouseOut="this.currentState='State1'"/>
<s:Label text="${product.listPrice}" id="price"/>
<s:Button label="AddToCart" id="add"
click="addToCart(product )"/>
<s:Button label="Remove From Cart" id="remove"
click="removeFromCart(product )"/>
</s:VGroup>
<!-- 商品详细信息 -->
<s:VGroup includeIn="expanded" x="200" width="100%">
<s:RichText text="{product.description}"
width="50%"/>
<s:Label text="Certified Organic"
visible="{product.isOrganic}"/>
<s:Label text="Low Fat"
visible="{product.isLowFat}"/>
</s:VGroup>
</s:DataRenderer>