计算ListBox中可见项目的数量

2024-05-07

我有一个名为 Book 的课程;

class Book
{
    public string Name { get; set; }
    public string Author { get; set; }
    public int PagesCount { get; set; }
    public int Category { get; set; }
}

ListBox 显示书籍列表,并且 ItemTemplate 已被修改以便直观地表示书籍。文本显示书名、作者和页数。然而,类别由某种颜色表示(例如,历史是蓝色,浪漫是红色等)。现在,文本具有 OuterGlowBitmap 效果和从类别 (int) 到适当颜色的值转换器。一切都绑定在 ListBoxItem 的 DataTemplate 中。从技术上讲,一切正常。

然而,问题在于性能。看起来,outerGlow 位图效果对处理器的影响很大,因此当我有大约 500 本书的列表时,从数据库检索数据需要大约 500 毫秒,但实际将项目加载到列表框中大约需要 10 秒。即使加载完成,滚动也非常缓慢。我尝试将 VirtualizingStackPanel.IsVirtualizing 设置为 True,但无济于事。 (在任何给定时间数据库中可以存储的最大书籍数量约为 30000 册。)

然而,即使列表框中有超过 100 个项目,人类大脑也无法快速处理,因此我的目的不是加载并向用户列出所有搜索到的书籍。这就是为什么我创建了一个包装导航类 BookNavigator,它实际上将列表框绑定到其 ObservableCollection 对象。所有书籍都加载到此 BookNavigator 中,但只有 X 本书显示在列表框中(通过将它们添加到 observableCollection)。

问题是我希望显示的书籍数量足够小,以便列表框不显示滚动条,这样我就可以实现自己的滚动方法(第一个、上一个、下一个、最后一个,或者只是我自己的滚动条,不没关系)。

如何计算要显示的项目数以便不显示滚动条?

弹出的两个问题: - 调整应用程序的大小可以更改列表框的大小 - 并非所有列表框项目都具有相同的高度(取决于作者的数量)。

有什么办法可以实现我想做的事情吗?


编辑(作为对马丁·哈里斯的回复)

Martin Harris 建议的代码的问题是 foreach 循环使用 FrameworkElement,但列表框填充了 Book 类型的对象,该对象不从 FrameworkElement 继承,也没有任何其他方法来计算其高度。 ListBoxItem 的根元素是一个网格,所以也许可以检索这个网格,但我不知道该怎么做?

有什么方法可以获取为表示列表框项目而创建的实际 UI 元素吗?


EDIT

我发现这个 Q/A 似乎正是我所需要的..项目容器生成器 https://stackoverflow.com/questions/610343/wpf-listbox-getting-uielement-instead-of-of-selecteditem


在尝试找出类似的东西后,我想我应该在这里分享我的结果(因为它似乎比其他回复更容易):

我得到的简单可见性测试here https://stackoverflow.com/questions/1517743/in-wpf-how-can-i-determine-whether-a-control-is-visible-to-the-user.

private static bool IsUserVisible(FrameworkElement element, FrameworkElement container)
{
    if (!element.IsVisible)
        return false;

    Rect bounds =
        element.TransformToAncestor(container).TransformBounds(new Rect(0.0, 0.0, element.ActualWidth, element.ActualHeight));
    var rect = new Rect(0.0, 0.0, container.ActualWidth, container.ActualHeight);
    return rect.Contains(bounds.TopLeft) || rect.Contains(bounds.BottomRight);
}

之后,您可以循环遍历列表框项目并使用该测试来确定哪些是可见的。该列表的计数将为您提供列表框中可见项目的数量。

private List<object> GetVisibleItemsFromListbox(ListBox listBox, FrameworkElement parentToTestVisibility)
{
    var items = new List<object>();

    foreach (var item in PhotosListBox.Items)
    {
        if (IsUserVisible((ListBoxItem)listBox.ItemContainerGenerator.ContainerFromItem(item), parentToTestVisibility))
        {
            items.Add(item);
        }
        else if (items.Any())
        {
            break;
        }
    }

    return items;
}

然后,这将包含列表框中当前显示的项目列表(包括通过滚动或类似方式隐藏的项目)。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

计算ListBox中可见项目的数量 的相关文章

随机推荐