在逻辑删除之后恢复LongListSelector中的滚动位置

时间:2011-06-13 06:33:36

标签: windows-phone-7 silverlight-toolkit tombstoning

我正在尝试使用WP7 Silverlight Toolkit中的LongListSelector控件。这需要一些工作,但我终于让它与我的应用程序一起工作。不幸的是,我在处理墓碑过程时遇到了一些麻烦。

当应用程序逻辑删除(或用户通过选择列表中的项目导航到另一个页面)时,我会保存列表中最顶层可见项目的副本。我将它保存到类变量和app状态集合中。

ICollection<object> visibleItems = myLongList.GetItemsInView();
_lastItem = null;
if (visibleItems.Count > 0)
    _lastItem = visibleItems.First();
IDictionary<string, object> state = 
              Microsoft.Phone.Shell.PhoneApplicationService.Current.State;
state["IndexByName_LastTopItem"] = _lastItem;

然后,当用户返回页面时,我检查两个值中的一个(状态或变量)并使用它来恢复最后一个滚动位置。

if (_lastItem == null) 
{ 
    if (state.ContainsKey("IndexByName_LastTopItem")) 
    { 
        _lastItem = state["IndexByName_LastTopItem"] as Chemical; 
    } 
} 

if (_lastItem != null) 
    Dispatcher.BeginInvoke(() => { myLongList.ScrollTo(_lastItem); }); 

除非应用程序墓碑,否则这很有用。在这种情况下,我没有收到任何错误,但列表完全空白,直到我触摸并拖动。一旦我这样做,它会重新显示在列表的顶部。我看了一下控件的来源,发现当你调用.ScrollTo(对象)时,它没有得到匹配。进一步调查发现,在搜索要滚动的项目时,使用==而不是等于进行比较。我只覆盖了Equals,显然默认==比较(按设计)引用。在逻辑删除后恢复状态项时,引用不匹配。 我可以覆盖==,但这感觉不对。我可以改变并重建控制源来调用equals(我试过并且它有效),但它是由比我更聪明的人写的,我想知道我是不是得到它。 还有更好的方法吗?

2 个答案:

答案 0 :(得分:2)

这是我最终提出的解决方案......

由于源代码可以免费用于Toolkit,我最终编辑了LongListSelector源代码来调用.Equals而不是==。它似乎适用于我的用例,我想我会分享以防其他人发现它有用......

在LongListSelector.cs中找到GetFlattenedIndex(对象项)函数并替换

if (item == _flattenedItems[index].Item)

if (item.Equals(_flattenedItems[index].Item))

然后在同一个文件中找到GetResolvedIndex(object item,out ContentPresenter contentPresenter)函数并替换

if (node.Value.Content == item)  // Nov 2010 Release
// OR
if (_flattenedItems[index].Item == item)  // Feb 2011 Release

if (item.Equals(node.Value.Content))  // Nov 2010 Release
// OR
if (item.Equals(_flattenedItems[index].Item))  // Feb 2011 Release

请注意,替换取决于您使用的工具包下载!

对控件进行这些更改后,它将正确匹配ScrollTo(对象)中指定的对象,即使引用不相等,只要您正确覆盖LongListSelector中显示的所有对象类型的Equals即可。不要忘记,如果您有分组列表,这适用于您的分组类以及您的项目类!

答案 1 :(得分:0)

您可以尝试在新列表中获取该项目吗?

var _goodReference = myList.FirstOrDefault(x => x.id == _lastItem.Id);

if (_goodReference != null)     
Dispatcher.BeginInvoke(() => { myLongList.ScrollTo(_goodReference); });