-1

フッター付きの DataGrid を作成するソリューションを検索しましたが、高度な DataGrid でそれを行うアイデアを見つけましたが、非常に難しいようです。

DataGrid のフッターの簡単な解決策をご存知ですか。

どうもありがとう

4

1 に答える 1

1

昨日、dataGridフッターに関する私自身の問題の中で、この質問に出くわしました。それ以来、私はそれを解決することができましたが、答えがないため (これは古い質問であることを認識しています)、誰かがまだ解決策を必要としている可能性があるため、ここに投稿します。

最終結果は次のようになります: http://prntscr.com/5cka32

はじめましょう:

最初にフッター サポートを提供するには、UIComponent を拡張するDataGridFooterBaseクラスを作成する必要があります。mx_internal 名前空間に属する 2 つのプロパティ (visibleColumns:Array と footerItemsChanged:Boolean) をそれに追加します (システムだけがそれらを表示できるようにする必要があると判断しました)。

public class DataGridFooterBase extends UIComponent
{
    mx_internal var visibleColumns:Array;
    mx_internal var footerItemsChanged:Boolean;

    public function DataGridFooterBase()
    {
        super();
    }
}

次に、 DataGridFooterBaseクラスを拡張する実際の DataGridFooter クラスを作成します。基本的に、このクラスは、フッターに表示されるオブジェクトであるICollection dataProviderを受け取ります。このシナリオを想像してみてください。請求書に関する情報が存在するグリッドがあります。amount*price 列の下にすべての請求書の合計を表示する必要があります。ただし、請求書には異なる通貨 (ユーロとドル) を使用できるため、通貨ごとに合計を表示する必要があります。そのため、行と列を表す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()メソッドを実装する必要があります。彼らはすべてがきちんと整頓されていることを保証します。したがって、これら 2 つのメソッドをオーバーライドできます。

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とは何なのか疑問に思っている方のために、私はこれを使用してフッターに色を付け、dataGrid 行とは異なるようにしています。その後、dataProvider が変更されたかどうかを確認するcommitProperties()メソッドをオーバーライドする必要があります。そうであった場合、表示リストを更新する前にすべてのフッター要素を再描画する必要があります (そうしないと、パフォーマンスの問題が発生します)

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に追加および削除する実際のメソッドが必要です。それでは、 addListItems()removeListItems()の 2 つのメソッドを作成しましょう。

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);
}

これら 2 つのメソッドは基本的に、すべての表示可能な列を取得し、dataProvider コレクション (footerItems[行][列]) の各項目に対して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クラスを続けましょう。DataGrid クラスを拡張する新しい Grid クラスを作成する必要があります。

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; ではないことを願っています。:) 乾杯。

于 2014-12-02T20:45:43.243 に答える