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

发布于 2024-11-15 15:18:45 字数 1272 浏览 2 评论 0原文

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

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

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(object) 时,它没有匹配。进一步的调查发现,当搜索要滚动到的项目时,它使用 == 而不是 Equals 进行比较。我只覆盖了 Equals,显然默认的 == 比较(按设计)引用。当您在逻辑删除后恢复状态项时,引用不匹配。 我可以覆盖 ==,但这感觉不对。我可以更改并重建控制源来调用 equals (我尝试过并且它有效),但它是由比我聪明得多的人编写的,我想知道我是否只是不明白。 有更好的办法吗?

I'm trying to work with the LongListSelector control from the WP7 Silverlight Toolkit. It's taken a bit of work, but I finally have it working with my app. Unfortunately, I am having some trouble properly handling the tombstoning process.

When the application tombstones (or the user navigates to another page by selecting an item in the list), I save a copy of the topmost visible item in the list. I save it to both a class variable and to the app state collection.

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;

Then, when the user returns to the page I check for one of the two values (state or variable) and use it to restore the last scroll position.

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

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

This works great unless the application tombstones. In that case I don't get any errors, but the list is completely blank until I touch it and drag. Once I do that, it redisplays at the top of the list. I took a look at the source for the control and found that when you call .ScrollTo(object) it doesn't get a match. Further investigation identified that when searching for an item to scroll to, it compares using == instead of Equals. I only overrode Equals, and apparently the default == compares (by design) references. When you restore a State item after tombstoning the references don't match.
I can override ==, but that feels wrong. I can change and rebuild the control source to call equals instead (I tried and it worked), but it was written by people much smarter than I and I'm wondering if I just don't get it.
Is there a better way?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

剪不断理还乱 2024-11-22 15:18:45

这是我最终提出的修复方案...

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

在 LongListSelector.cs 中找到 GetFlattenedIndex(object item) 函数并替换

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(object) 中指定的对象,即使引用不相等,只要您为 LongListSelector 中显示的所有对象类型正确重写 Equals 即可。不要忘记这适用于您的分组类以及您的项目类(如果您有分组列表)!

This is the fix I ended up coming up with...

Since the source code is freely available for the Toolkit, I ended up editing the LongListSelector source code to call .Equals instead of ==. It seems to work properly for my use case and I thought I'd share in case anyone else finds it useful...

in LongListSelector.cs find the GetFlattenedIndex(object item) function and replace

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

with

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

and then in the same file find the GetResolvedIndex(object item, out ContentPresenter contentPresenter) function and replace

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

with

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

NOTE that the replace depends on which toolkit download you are using!

Once you have made these changes to the control, it will properly match up objects specified in ScrollTo(object), even if the references are not equal as long as you properly override Equals for all object types displayed in your LongListSelector. Don't forget this applies to your Grouping class as well as your item class if you have a grouped list!

随风而去 2024-11-22 15:18:45

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

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

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

Can you try to get the item in the new list ?

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

if (_goodReference != null)     
Dispatcher.BeginInvoke(() => { myLongList.ScrollTo(_goodReference); }); 
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文