Flex:spark DataGrid显示dataProvider中当前值以外的值

时间:2012-05-08 18:00:16

标签: actionscript-3 flex actionscript flex4

我在屏幕上有2个flex datagrids。用户可以从任一数据网格中选择一行或多行,并将它们移动到另一个数据网格。进入应用程序时,下表为空。例如:

Item    Color   Price
--------------------
item57  red    $5.55
item62  blue   $5.29
item808 green  $2.21

Row  Item    Color   Price
---------------------------

请注意,有一列对底部数据网格中的行进行编号(仅限)。

当我进入应用程序并移动时,例如,从顶部到底部网格移动3行,行号很好(它们显示行1,2和3)。例如:

Item    Color   Price
--------------------

Row  Item    Color   Price
---------------------------
1    item57  red    $5.55
2    item62  blue   $5.29
3    item808 green  $2.21

如果我然后移动,例如,底部网格中的第1行返回顶部...

Item    Color   Price
--------------------
item57  red    $5.55

Row  Item    Color   Price
---------------------------
1    item62  blue   $5.29
2    item808 green  $2.21

然后再回到底部网格......

Item    Color   Price
--------------------


Row  Item    Color   Price
---------------------------
1    item62  blue   $5.29
2    item808 green  $2.21
1    item57  red    $5.55

行号应该显示为3,因为它插入到列表末尾的底部网格中,但是当它执行此操作时,它会显示(旧)行号值为1。

当我调试并查看dataprovider = _myData时,我看到有问题的行的rowNumber值(对于上面的item57)等于3(应该如此)。但是,它在下部数据网格中显示为1。

dataprovider值如何与DataGrid中显示的值不同?

[我还可以调试并查看gridLower列信息,并为相关数据显示rowNumber的正确值3。]

下层数据网格类似于以下内容(虽然我使用的是自定义itemRenderer,为简单起见,此处已删除):

[Bindable]
private var _myData:ListCollectionView=new ListCollectionView(new ArrayList());
...
<s:DataGrid dataProvider="{_myData}">
    <s:columns>
        <fx:Array>
            <s:GridColumn id="gridLower" headerText="myHeader" dataField="rowNumber"/>  
            ...

将上表的行添加到下表的函数是:

private function addRow():void {    
    var selectedIndices:Object=gridUpper.grid.selectedIndices;
    for (var i:int=selectedIndices.length-1;i>=0;i--) {
        var item:Object=_upperTableData.removeItemAt(selectedIndices[i]);
        item.rowNumber=_myData.length+1;
        _myData.list.addItem(item);
    } 
    // I tried adding "_myData.refresh();" here and it had no effect
    // I tried adding "ListCollectionView(gridLower.dataProvider).refresh();" and it had no effect
    // I tried adding "grid2.dataProvider.refresh();" here but it had no effect
}

更新1:如果我对下表中的任何列重新排序,则会显示正确的值。我似乎在观察此链接中的报告: http://www.barneyb.com/barneyblog/2007/06/23/another-flex-weirdnessgotcha/ 但是还没有找到解决方案。在上面的addRow()函数中查看尝试次数。我是在正确的轨道上吗?

更新2:虽然重新排序手动纠正较低网格中的数据,但我还没有找到以编程方式执行此操作的方法。我试着插入:

_myData.sort=null;
var complete:Boolean=_myData.refresh();

就在上面的addRow()函数结束之前,但它没有解决我的问题。调试时,complete为真,但下面的网格仍显示过时数据。

2 个答案:

答案 0 :(得分:1)

新答案:)如果有帮助,我会删除旧的。

我还没有使用Spark DataGrid,期望它的行为像List。

在DataGrid的这个方法的源代码中的一些注释中找到了这个:

public function invalidateCell(rowIndex:int, columnIndex:int):void

您可以通过为另一个值传递-1来使整个行/列无效。在下面文档的引用中,您还可以使用dataProvider.itemUpdated()

  

如果指定的单元格可见,则会重新显示该单元格。如果   variableRowHeight = true,然后这样做可能会导致高度   相应的行要改变。如果columnIndex为-1,则为整行   无效。同样,如果rowIndex为-1,则整个列为   无效。

     

当任何方面发生变化时,应该调用此方法   rowIndex中的数据提供程序项可能会对其产生一些影响   显示指定单元格的方式。调用此方法类似于   调用dataProvider.itemUpdated()方法,该方法建议Grid   显示指定项目的所有行都应重新显示。   使用这种方法可以相对有效,因为它缩小了   单个单元格的更改范围。

现在我终于知道了集合(ArrayCollection,ListCollectionView)上的itemUpdated()方法实际可以在哪里使用了!

[编辑]

为您的网格指定一个ID:

<s:DataGrid id="lowerDataGrid" dataProvider="{_myData}">

然后,您应该可以在更新集合后使用addRow()方法执行此操作:

lowerDataGrid.invalidateCell(item.rowNmber -1, 1); // assuming rowNumbers are 0 based

答案 1 :(得分:0)

在我的情况下,在我的主类中包含网格作为元素,每当我想强制刷新所有单元格时:

    gridsDataProvider.addItemAt(new Object(), 0);
    gridsDataProvider.removeItemAt(0);

但是我的GridItemRenderer需要满足数据的变化。所以我创建了一个updateDisplay方法:

        private function updateDisplay() : void {
            if (transWindow != null) {
                if (data == transWindow.total) {
                    if (field != "vat" && field != "total") {
                        textInput.visible = false;
                    } else {
                        line.visible = true;
                        textInput.enabled = false;
                        textInput.setStyle("fontWeight", "bold");
                        textInput.setStyle("fontSize", 14);
                    }
                } else {
                    line.visible = false;
                    textInput.visible = true;
                    textInput.enabled = true;
                    textInput.setStyle("fontWeight", "normal");
                    textInput.setStyle("fontSize", 12);
                }
            }
        }

从creationComplete处理程序...

调用此方法
        protected function init(event:FlexEvent):void
        {
            getTransWindow(event.target.automationOwner);
            updateDisplay();
        }

......以及GridItemRenderer的数据设定者

        override public function set data(v:Object):void {
            super.data = v;
            if (v == null) {
                textInput.text = "";
                return;
            }
            var value : * = v[field];
            if (value == null || value == undefined) {
                textInput.text = "";
                return;
            }
            if (value is Number)
                textInput.text = Number(value).toFixed(2);
            else
                textInput.text = ""+value;
            updateDisplay();
        }

我的渲染器的mxml主体非常简单:

<s:Line id="line" width="100%" visible="false" yFrom="1" yTo="1">
    <s:stroke>
        <s:SolidColorStroke color="0" weight="0"/>
    </s:stroke>
</s:Line>
<s:TextInput id="textInput" y="2" restrict="0123456789." width="100%" height="100%" minWidth="10" borderVisible="false" textAlign="right"/>

O,如果你想知道,getTransWindow方法只是一个检索包含网格的主调用类的方法:

private function getTransWindow(par : *) : void {
            if (transWindow != null)
                return;
            transWindow = par;
            while (!(transWindow is TransactionWindow)) {
                transWindow = transWindow.parent;
            }
        }

希望这能节省一些时间

此致 克里斯托