我搜索了一个使用页脚创建 DataGrid 的解决方案,我发现一些想法可以使用高级 DataGrid 来做到这一点,但它看起来非常困难。
那么您知道 DataGrid 上的页脚的简单解决方案吗?
非常感谢
我搜索了一个使用页脚创建 DataGrid 的解决方案,我发现一些想法可以使用高级 DataGrid 来做到这一点,但它看起来非常困难。
那么您知道 DataGrid 上的页脚的简单解决方案吗?
非常感谢
我昨天在我自己的 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();
}
如果您想知道graphics是什么,我用它来为 Footer 着色,使其与 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对象添加和删除到我们的新Footer的实际方法。所以让我们创建 2 个方法,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 集合(footerItems[row][column])中的每个项目创建一个DataGridItemRenderer,并将它们添加到我们的 Footer 类的显示列表中,或者删除它们。我们在此类中需要的最后一个方法将确保所有项目都根据它们“所属”的列正确定位。
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;
}
}
我相信这门课或多或少是不言自明的。要将值设置为页脚,您需要使用setFooterValues()函数,您可以使用单个对象或对象的ICollection。您需要做的另一件事是,如果您希望页脚中有多行,则需要显式设置footerHeight属性(或修改Footer 类中的measure()方法以根据集合中的项目数自动缩放)。
我们需要做的最后一件事是修改DataGridColumn类,为IListItemRenderer添加一个存储。这里是:
public class GridColumn extends DataGridColumn
{
mx_internal var cachedFooterRenderer:IListItemRenderer;
public function GridColumn(columnName:String=null)
{
super(columnName);
}
}
就是这样。希望这对某人有所帮助,并且不是 TL;DR;:) 干杯。