我搜索一个解决方案,用页脚创建DataGrid,我发现有一些想法用avanced DataGrid来做,但看起来很难。
您是否知道DataGrid上的页脚的简单解决方案。
非常感谢
答案 0 :(得分:1)
我在昨天遇到dataGrid页脚问题时遇到了这个问题。 从那以后我设法解决了,因为没有答案(我知道这是一个老问题),有人可能仍然需要一个解决方案,我会在这里发布。
最终结果应该是这样的: http://prntscr.com/5cka32
让我们开始吧:
首先提供页脚支持,我们需要创建一个扩展UIComponent的 DataGridFooterBase 类。 向它添加属于mx_internal命名空间的两个属性(visibleColumns:Array和footerItemsChanged:Boolean)(我决定只有系统需要能够看到它们)。
public class DataGridFooterBase extends UIComponent
{
mx_internal var visibleColumns:Array;
mx_internal var footerItemsChanged:Boolean;
public function DataGridFooterBase()
{
super();
}
}
接下来,我们将创建实际的 DataGridFooter 类,它将扩展 DataGridFooterBase 类。 基本上,这个类将接收一个 ICollection dataProvider,其中的对象将显示在页脚中。想象一下这个场景,你有一个网格,其中有关于发票的信息。您需要在金额*价格列下方显示所有发票的总和。 但是,发票可以有不同的货币(欧元和美元),您需要按货币显示总和。这就是为什么我们有一个 ICollection 类型的dataProvider,它将代表行和列。
public class DataGridFooter extends DataGridFooterBase
{
protected var dataGrid:Grid;
protected var footerItems:Array=[];
protected var cachedFooterHeight:Number=0;
protected var cachedPaddingBottom:Number=0;
protected var cachedPaddingTop:Number=0;
private var _dataProvider:Object;
public var leftOffset:Number=0;
public var topOffset:Number=0;
public var rightOffset:Number=0;
public var bottomOffset:Number=0;
public function DataGridFooter()
{
super();
}
public function set dataProvider(value:Object):void
{
if (value != null && !(value is ArrayCollection))
value=new ArrayCollection([value]);
_dataProvider=value;
footerItemsChanged=true;
}
public function get dataProvider():Object
{
return _dataProvider;
}
override protected function createChildren():void
{
dataGrid=parent as Grid;
}
}
这是一个基本设置。接下来,我们需要实现 measure()和 updateDisplayList()方法。 他们将确保一切都很好和整洁。 所以让我们覆盖这两种方法:
override protected function measure():void
{
super.measure();
cachedFooterHeight=dataGrid._explicitFooterHeight ? dataGrid.footerHeight : 22;
cachedPaddingBottom=getStyle("paddingBottom");
cachedPaddingTop=getStyle("paddingTop");
measuredHeight=cachedFooterHeight;
}
override protected function updateDisplayList(w:Number, h:Number):void
{
graphics.clear();
graphics.beginFill(0xCFCFCF);
graphics.drawRect(0, 0, unscaledWidth, unscaledHeight);
graphics.endFill();
graphics.lineStyle(1, 0x696969);
graphics.moveTo(0, 0);
graphics.lineTo(unscaledWidth, 0);
graphics.endFill();
updateFooterItemsLayout();
}
如果你想知道图形是什么,我用它来为页脚着色,使其与dataGrid行不同。之后我们需要覆盖 commitProperties()方法,在该方法中我们检查dataProvider是否已更改。如果是,我们需要在更新显示列表之前重新绘制所有页脚元素(否则会出现性能问题)
override protected function commitProperties():void
{
super.commitProperties();
if (footerItemsChanged)
{
footerItemsChanged=false;
clearListItems();
var cols:Array=visibleColumns;
if ((cols && cols.length > 0 || dataGrid.footerVisible))
{
if (_dataProvider != null)
{
for (var j:int=0; j < _dataProvider.length; j++)
{
addListItems(j, dataProvider.getItemAt(j));
}
}
else
{
addListItems(0, null);
}
}
}
}
让我们继续,到目前为止的一切都是准备,现在我们需要实际的方法,将 IListItemRenderer 对象添加到新的页脚中。 那么让我们创建两个方法, addListItems()和 removeListItems()
private function addListItems(row:int=0, data:Object=null):void
{
if (footerItems == null)
return;
var cols:Array=visibleColumns;
footerItems[row]=[];
var rowData:DataGridListData;
var item:IListItemRenderer;
var colNum:int=0;
var column:GridColumn;
while (cols && colNum < cols.length)
{
column=cols[colNum];
item=ObjectUtil.copy(column.cachedFooterRenderer) as IListItemRenderer;
if (item == null)
{
item=new DataGridItemRenderer();
item.styleName=column;
column.cachedFooterRenderer=item;
}
var label:String="";
if (data != null)
{
if (column.labelFunction == null)
label=String(AbcUtils.findValueInObject(data, column.dataField.split(".")));
else
label=String(column.labelFunction(data, column));
if (label == null || label == "null" || label == "NaN")
label="";
}
rowData=new DataGridListData(label, column.dataField, colNum, uid, dataGrid, 0);
if (item is IDropInListItemRenderer)
IDropInListItemRenderer(item).listData=rowData;
item.data=column;
item.visible=true;
addChild(DisplayObject(item));
footerItems[row][colNum]=item;
colNum++;
}
}
private function clearListItems():void
{
if (footerItems == null)
return;
for (var rows:int=0; rows < footerItems.length; rows++)
{
var cols:Array=footerItems[rows];
for (var i:int=0; i < cols.length; i++)
{
removeChild(DisplayObject(cols[i]));
}
}
footerItems.splice(0, footerItems.length);
}
这两种方法基本上做了什么,它们采用所有可见列并为dataProvider集合中的每个项目创建 DataGridItemRenderer (footerItems [row] [column]),并将它们添加到我们的显示列表中页脚类,或删除它们。我们在此类中需要的最后一个方法将确保所有项目都根据它们“所属”的列正确定位。
private function updateFooterItemsLayout():void
{
if (_dataProvider == null || footerItems == null || footerItems.length == 0)
return;
for (var row:int=0; row < _dataProvider.length; row++)
{
var cols:Array=visibleColumns;
var item:IListItemRenderer;
var colNum:int=0;
var ww:Number=0;
var xx:Number=0;
var column:GridColumn;
while (cols && colNum < cols.length)
{
column=cols[colNum];
item=footerItems[row][colNum];
item.explicitWidth=ww=column.width;
UIComponentGlobals.layoutManager.validateClient(item, true);
item.setActualSize(ww, item.getExplicitOrMeasuredHeight());
if (row == 0)
item.move(xx, cachedPaddingTop);
else
item.move(xx, item.height * row + cachedPaddingTop);
xx+=ww;
colNum++;
}
}
}
基本上就是这样。现在我们需要调整DataGrid和DataGridColumn类来连接我们的新Footer类。
让我们继续使用 DataGrid 类。我们需要创建一个新的Grid类,它将扩展DataGrid类。
public class Grid extends DataGrid
{
public function Grid()
{
super();
}
//==== footer specific stuff =======
protected var footer:DataGridFooterBase;
mx_internal var footerClass:Class=DataGridFooter;
private var _enableFooter:Boolean;
private var _footerHeight:int=22;
mx_internal var _explicitFooterHeight:Boolean;
mx_internal function get dataGridFooter():DataGridFooterBase
{
return footer;
}
[Bindable("enableFootersChanged")]
[Inspectable(category="General", defaultValue="false")]
public function get enableFooters():Boolean
{
return _enableFooter;
}
public function set enableFooters(value:Boolean):void
{
if (value == _enableFooter)
return;
_enableFooter=enabled;
invalidateDisplayList();
dispatchEvent(new Event("enableFootersChanged"));
}
mx_internal function get footerVisible():Boolean
{
return enableFooters && (footerHeight > 0) && footer != null;
}
[Bindable("resize")]
[Inspectable(category="General", defaultValue="22")]
public function get footerHeight():Number
{
return _footerHeight;
}
public function set footerHeight(value:Number):void
{
_footerHeight=value;
_explicitFooterHeight=true;
invalidateDisplayList();
}
public function setFooterValues(value:Object):void
{
if (footer != null)
DataGridFooter(footer).dataProvider=value;
}
//==========================================
override protected function createChildren():void
{
super.createChildren();
if (enableFooters && footer == null)
{
footer=new footerClass();
addChild(footer);
}
}
override public function invalidateDisplayList():void
{
super.invalidateDisplayList();
if (footer != null)
{
footer.invalidateSize();
footer.invalidateDisplayList();
}
}
override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
{
super.updateDisplayList(unscaledWidth, unscaledHeight);
if (footer != null)
{
footer.visibleColumns=visibleColumns;
footer.invalidateSize();
footer.validateNow();
}
if (footerVisible && verticalScrollBar && verticalScrollBar.visible)
{
var maxHeight:Number=this.verticalScrollBar.height - this.footer.height;
verticalScrollBar.setActualSize(verticalScrollBar.width, maxHeight);
}
}
override protected function adjustListContent(unscaledWidth:Number=-1, unscaledHeight:Number=-1):void
{
super.adjustListContent(unscaledWidth, unscaledHeight);
var refY:Number=header.height;
var additionalReservedHeight:Number=0;
additionalReservedHeight+=footerVisible ? footerHeight : 0;
listContent.setActualSize(listContent.width, listContent.height - additionalReservedHeight);
refY+=listContent.height;
if (footerVisible)
{
footer.move(listContent.x, refY);
footer.setActualSize(listContent.width, footerHeight);
refY+=footer.height;
}
}
override protected function measure():void
{
super.measure();
var additionalReservedHeight:Number=0;
if (enableFooters)
additionalReservedHeight+=footerHeight;
this.measuredHeight=header.getExplicitOrMeasuredHeight() + additionalReservedHeight + (rowHeight * rowCount) + viewMetrics.bottom + viewMetrics.top;
this.measuredMinHeight=header.getExplicitOrMeasuredHeight() + additionalReservedHeight + (rowHeight * rowCount) + viewMetrics.bottom + viewMetrics.top;
}
}
我相信这个课程或多或少是自我解释的。要将值设置为Footer,您需要使用 setFooterValues()功能,您可以使用单个对象或 ICollection 对象。你需要做的另一件事,如果你希望你的页脚中有多行,你需要在页脚中明确设置 footerHeight 属性(或修改 measure()方法类根据集合中的项目数自动缩放。)
我们最不需要的是修改 DataGridColumn 类,为 IListItemRenderer 添加存储空间。 这是:
public class GridColumn extends DataGridColumn
{
mx_internal var cachedFooterRenderer:IListItemRenderer;
public function GridColumn(columnName:String=null)
{
super(columnName);
}
}
就是这样。希望这有助于某人,而不是TL; DR; :) 欢呼声。