Apache flex 如何防止列表在数据提供程序刷新/更新/更改时滚动?

Apache flex 如何防止列表在数据提供程序刷新/更新/更改时滚动?,apache-flex,list,selection,dataprovider,Apache Flex,List,Selection,Dataprovider,我有一个简单的列表和一个后台刷新协议 当列表向下滚动时,刷新会将其滚动回顶部。我想阻止这一切 我已尝试捕捉收藏更改事件并 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

我有一个简单的列表和一个后台刷新协议

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

我已尝试捕捉收藏更改事件并

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中)

我不喜欢使用计时器、ENTER_FRAME或callLater(),但我似乎想不出办法

我能看到的唯一其他选择是对列表进行子分类,以便它能够捕获皮肤中的数据组抛出的dataProviderChanged事件


有什么想法吗?

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

当列表中有新数据时(刷新后),循环浏览新数据对象列表,将这些对象中的属性复制到支持列表的集合中的对象中。通常,您将根据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);
  }
}

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

当列表中有新数据时(刷新后),循环浏览新数据对象列表,将这些对象中的属性复制到支持列表的集合中的对象中。通常,您将根据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);
  }
}

我会尝试解释我的方法…如果你仍然不确定,让我知道,我会给你的源代码以及

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


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

我将尝试解释我的方法……如果您仍然不确定,请告诉我,我也会给您源代码

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


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

我针对此问题的解决方案是针对特定情况,但是它的优点是非常简单,所以也许你可以从中画出适合你需要的东西。由于我不知道您正试图解决的问题是什么,我将向您描述我的问题:

我有一个从服务器逐步加载数据的列表。当用户向下滚动并将下一批项目添加到数据提供程序时,scrollposition将跳回起始位置

解决方法很简单,就是停止COLLECTION_CHANGE事件的传播,这样列表就不会捕获它

myDataProvider.addEventListener(
    CollectionEvent.COLLECTION_CHANGE, preventRefresh
);

private function preventRefresh(event:CollectionEvent):void {
    event.stopImmediatePropagation();
}
您必须知道,这有效地防止了列表组件的重画,因此不会显示任何添加的项。这对我来说不是问题,因为项目将添加到列表的末尾(在视口之外),当用户滚动时,列表将自动重新绘制,并显示新项目。也许在你的情况下,如果需要,你可以强制重画


加载所有项目后,我可以删除事件侦听器并返回列表组件的正常行为。

我针对此问题的解决方案针对特定情况,但它的优点是非常简单,因此您可以从中提取适合您需要的内容。由于我不知道您正试图解决的问题是什么,我将向您描述我的问题:

我有一个从服务器逐步加载数据的列表。当用户向下滚动并将下一批项目添加到数据提供程序时,scrollposition将跳回起始位置

解决方法很简单,就是停止COLLECTION_CHANGE事件的传播,这样列表就不会捕获它

myDataProvider.addEventListener(
    CollectionEvent.COLLECTION_CHANGE, preventRefresh
);

private function preventRefresh(event:CollectionEvent):void {
    event.stopImmediatePropagation();
}
您必须知道,这有效地防止了列表组件的重画,因此不会显示任何添加的项。这对我来说不是问题,因为项目将添加到列表的末尾(在视口之外),当用户滚动时,列表将自动重新绘制,并显示新项目。也许在你的情况下,如果需要,你可以强制重画

加载所有项目后,我可以删除事件侦听器并返回正常行为