2011-06-30 177 views
1

我有一个简单的列表和后台刷新协议。如何保持滚动dataProvider刷新/更新/更改列表?

当列表向下滚动时,刷新会将其滚动回顶部。我想阻止这一点。

我试图捕捉COLLECTION_CHANGE事件和

validateNow(); // try to get the component to reset to the new data 

list.ensureIndexIsVisible(previousIndex); // actually, I search for the previous data id in the IList, but that's not important 

失败的原因是名单的变化(在DataGroup.commitProperties)后自行复位

我讨厌使用Timer,ENTER_FRAME或callLater(),但我似乎无法找到一种方法。

我可以看到的唯一的其他替代方法是对子列进行子分类,以便它可以捕获皮肤中的DataGroup正在抛出的dataProviderChanged事件。

任何想法?

+0

集合的任何更新都可能会改变dataProvider的长度,因此保持相同的滚动位置并不总是实用。你正在更换dataProvider,还是只通过添加项目/删除项目/添加过滤器来更新它?你可以尝试设置保存/重置veritcalScrollPosition。我不确定这是否会导致视觉“凹凸”。 – JeffryHouser

+1

为什么你在第一个地方刷新?你在做什么收藏? –

+0

你看过添加一个事件监听器到像updateComplete的东西吗?我以前通过继承List和重写'set scrollPosition'来解决这类问题。 –

回答

2

我会试着解释我的方法......如果你仍然不确定让我知道,我也会给你源代码。

1)创建一个变量来存储视口的当前滚动位置。 2)为滚动条上的Event.CHANGE和MouseEvent.MOUSE_WHEEL添加事件侦听器,并用当前滚动位置更新步骤1中创建的变量; 3)在FlexEvent.UpdateComplete的视口中添加事件监听器,并将滚动位置设置为存储的变量。

简而言之,我们正在做的是每次用户与它交互时以及当我们的视口被更新时(由于数据提供者的改变),将滚动位置存储在变量中,我们只需设置我们先前存储的滚动位置变量。

2

我以前遇到过这个问题,并通过与匹配器一起使用数据代理模式来解决它。通过仅更新已更改的对象并仅更新现有对象的属性,为支持列表的集合编写一个匹配器。目标是避免在数据源刷新时创建新对象。

当列表有新数据(刷新后)时,循环显示新数据对象列表,将这些对象的属性复制到支持列表的集合中的对象中。通常你会匹配基于id的对象。旧列表中不存在的新列表中的任何对象都会被添加。您的滚动位置通常不会更改,通常会保留任何选择。

这里是一个例子。

for each(newObject:Object in newArrayValues){ 
    var found:Boolean = false; 
    for each(oldObject:Object in oldArrayValues){ 
    if(oldObject.id == newObject.id){ 
     found = true; 
     oldObject.myAttribute = newObject.myAttribute; 
     oldObject.myAttribute2 = newObject.myAttribute2; 
    } 
    } 
    if(!found){ 
    oldArrayValues.addItem(newObject); 
    } 
} 
+0

可悲的是,有时整个dataProvider是相同数据的新实例。我害怕增加这么多复杂性。 –

+0

这可以通过for循环来完成,如下所示: (newObject:newArrayValues中的对象){ var found:Boolean = false; (oldObject:oldArrayValues中的Object){ if(oldObject.id == newObject.id){ found = true; oldObject.myAttribute = newObject.myAttribute; oldObject.myAttribute2 = newObject.myAttribute2; (!found){ } oldArrayValues.addItem(newObject); } } – TroyJ

0

我对这个问题的解决方案是针对特定的情况,但它的优点是非常简单,所以也许你可以从中得出符合你需求的东西。由于我不知道你想要解决什么问题,我会给你一个我的描述:

我有一个逐渐从服务器加载数据的列表。当用户向下滚动并将下一批物品添加到数据提供者时,滚动位置将跳回到开始位置。

解决方法与停止COLLECTION_CHANGE事件的传播一样简单,以便List不会捕获它。

myDataProvider.addEventListener(
    CollectionEvent.COLLECTION_CHANGE, preventRefresh 
); 

private function preventRefresh(event:CollectionEvent):void { 
    event.stopImmediatePropagation(); 
} 

你要知道,这有效地防止了List组件的重绘,因此任何添加的项目将不被显示。这对我来说不是问题,因为这些项目将被添加到列表的末尾(视口外),并且当用户滚动时,列表将自动重绘,并且新项目将被显示。也许在你的情况下,你可以强制重绘,如果需要的话。

当所有项目都被加载后,我可以删除事件监听器并返回List组件的正常行为。

+0

我不能阻止刷新,因为我想要新的/删除/更改的项目显示 –

+0

在这种情况下,你将不得不继承列表并重写默认行为:( – RIAstar

4

实际上更好的解决方案是扩展DataGroup。你需要重写这个。

这里的所有解决方案都会在滚动条被重置为0并且它被设置回以前的值时创建一个闪烁。这看起来不对。这个解决方案没有任何闪烁,最好的是,你只需在代码中将DataGroup更改为FixedDataGroup,它就可以工作,不需要对代码进行其他更改;)。

享受家伙。

public class FixedDataGroup extends spark.components.DataGroup 
{ 
    private var _dataProviderChanged:Boolean; 
    private var _lastScrollPosition:Number = 0; 

    public function FixedDataGroup() 
    { 
     super(); 
    } 

    override public function set dataProvider(value:IList):void 
    { 
     if (this.dataProvider != null && value != this.dataProvider) 
     { 
      dataProvider.removeEventListener(CollectionEvent.COLLECTION_CHANGE, onDataProviderChanged); 
     } 
     super.dataProvider = value; 

     if (value != null) 
     { 
      value.addEventListener(CollectionEvent.COLLECTION_CHANGE, onDataProviderChanged); 
     } 
    } 

    override protected function commitProperties():void 
    { 
     var lastScrollPosition:Number = _lastScrollPosition; 

     super.commitProperties(); 

     if (_dataProviderChanged) 
     { 
      verticalScrollPosition = lastScrollPosition; 
     } 
    } 

    private function onDataProviderChanged(e:CollectionEvent):void 
    { 
     _dataProviderChanged = true; 
     invalidateProperties(); 
    } 

    override public function set verticalScrollPosition(value:Number):void 
    { 
     super.verticalScrollPosition = value; 
     _lastScrollPosition = value; 
    } 


} 
+0

这不工作,如果您使用'useVirtualLayout =“true”'这在许多情况下对性能的原因至关重要。 –