将嵌套容器 (virtualizingstackpanel) 虚拟化为 WPF 中的单个父滚动条

发布于 2024-07-30 03:53:04 字数 845 浏览 12 评论 0原文

我已经把自己编码成了这件事上的一个泡菜。 我正在编写一个自定义 WPF 控件,该控件类似于 这篇 MSDN 文章 以及网络上的许多其他地方。 目前,这个东西中有很大一部分是定制的,并且它很好地满足了我的目标,除了虚拟化方面之外。 我的重写 TreeViewTreeViewItem 模板都使用 VirtualizingStackPanel 来显示其项目,并且我已经验证所有这些都是按预期创建的。 虚拟化在根级别项目上正常工作(仅烹制当前在 ScrollViewer 中可见的 UI 元素),并且 TreeView 东西负责不生成元素对于折叠的节点。 当扩展一个节点时,问题就出现了——所有元素都是为节点中的每个子元素准备的,甚至是屏幕外的数千个元素。

在我看来,我所需要做的就是以某种方式将内部嵌套的 VirtualizingStackPanel 的滚动所有者属性设置为默认情况下根级别 VSP 连接到的同一主滚动视图,但我读了一篇MSFT 海报此处 说这行不通。

不幸的是,如果没有虚拟化发生,这件事就慢得像泥巴一样,所以我需要想出某种解决方案。 任何建议将不胜感激。

I've kind of coded myself into a pickle on this one. I am writing a custom WPF control which is similar to the TreeListView described in This MSDN article as well as many other places on the net. A pretty big pile of this thing is custom at this point, and it's meeting my goals fairly well, except on the virtualization front. My overriden TreeView and TreeViewItem templates both use VirtualizingStackPanels to present their items, and I've verified that all of this is getting created as expected. The virtualization works correctly on root level items (only the UI elements for those currently visible in the ScrollViewer are cooked up), and the TreeView stuff takes care of not generating the elements for collapsed nodes. The problem comes when expanding a node -- all the elements are cooked up for every child in the node, even the thousands that are offscreen.

It seemed to me like all I needed to do was somehow set the scrollowner property of the inner nested VirtualizingStackPanels to the same main scrollview that the root level VSP gets hooked up to by default, but I read an MSFT poster here saying that this will not work.

Unfortunately this thing is slow as mud without the virtualization occurring, so I need to come up with some sort of solution. Any suggestions would be greatly appreciated.

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

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

发布评论

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

评论(2

末が日狂欢 2024-08-06 03:53:04

我知道这是一个老问题,但仍然与我相关。

就我而言,我认为 TreeView 不会削减它,因为我正好需要两个层,并且两个层之间显示的项目类型不同。 另外,我正在重构 Expander 列表,因此我的思考更加一维。

但后来我意识到您可以自定义 TreeViewItemTemplate 以包含您自己的 HierarchicalDataTemplate,并且您可以自定义 ItemTemplateHierarchicalDataTemplate 与您自己定制的 DataTemplate... 快点! 正好两层,每一层都有不同的东西!

所以我的观点是,TreeView 足够灵活,您应该尽量不要创建自己的自定义控件。

这就是我所做的:

XAML:

<Page x:Class="Foo.Views.TreePage"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
      xmlns:local="clr-namespace:Foo.Views"
      xmlns:viewModel="clr-namespace:Foo.ViewModels"
      mc:Ignorable="d" 
      d:DesignHeight="300" d:DesignWidth="300"
      Title="Tree page"
      d:DataContext="{d:DesignInstance Type=viewModel:TreeModel}">
    <TreeView
        VirtualizingPanel.IsVirtualizing="True"
        VirtualizingPanel.VirtualizationMode="Recycling"
        ScrollViewer.CanContentScroll="True"
        VirtualizingPanel.ScrollUnit="Pixel"
        ItemsSource="{Binding Values}"><!-- IList<Person> -->
        <TreeView.ItemTemplate><!-- Template for first layer, which has a HierarchicalDataTemplate so that this layer will expand -->
            <HierarchicalDataTemplate
                ItemsSource="{Binding Expenses}"><!-- IList<Expense> -->
                <HierarchicalDataTemplate.ItemTemplate><!-- Template for the second layer, which has a DataTemplate instead of HierarchicalDataTemplate so that this layer won't expand -->
                    <DataTemplate>
                        <TextBlock Text="{Binding Amount}"/><!-- Expense amount in dollars -->
                    </DataTemplate>
                </HierarchicalDataTemplate.ItemTemplate>

                <TextBlock Text="{Binding Name}"/><!-- Person name -->
            </HierarchicalDataTemplate>
        </TreeView.ItemTemplate>
    </TreeView>
</Page>

Person 类:

public class Person
{
    public string Name { get; set; }
    public List<Expense> Expenses { get; set; }
}

Expense 类:

public class Expense
{
    public double Amount { get; set; }
}

如下所示:

上述代码实际运行的屏幕截图

我用 < a href="https://snoopwpf.codeplex.com/" rel="nofollow noreferrer">Snoop 证明是UI Virtualizing。 以下是应用程序较小时加载的 TreeViewItem 数量:

显示应用程序较小时元素数量的屏幕截图

...这是加载的 TreeViewItems(它不断超出此代码片段,但您明白了):

< img src="https://i.sstatic.net/YWx3l.png" alt="屏幕截图显示应用程序全屏时有更多元素">

现在只需简单地设计样式即可嵌套层看起来就是我想要的!

编辑:我刚刚验证了 TreeView 虚拟化了它的所有层,而不仅仅是第一层。

I know this is an old question, but was still relevant for me.

In my case I thought a TreeView wouldn't cut it because I need exactly two layers, and the types of items displayed are different between the two layers. Also, I'm refactoring a list of Expanders so I was thinking more one-dimensionally.

But then I realized that you can customize the ItemTemplate of the TreeView to include your own HierarchicalDataTemplate, and that you can customize the ItemTemplate of that HierarchicalDataTemplate with your own tailored DataTemplate... Presto! Exactly two layers with different things in each!

So my point is that the TreeView is flexible enough that you should try not to create your own custom control.

Here's what I did:

XAML:

<Page x:Class="Foo.Views.TreePage"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
      xmlns:local="clr-namespace:Foo.Views"
      xmlns:viewModel="clr-namespace:Foo.ViewModels"
      mc:Ignorable="d" 
      d:DesignHeight="300" d:DesignWidth="300"
      Title="Tree page"
      d:DataContext="{d:DesignInstance Type=viewModel:TreeModel}">
    <TreeView
        VirtualizingPanel.IsVirtualizing="True"
        VirtualizingPanel.VirtualizationMode="Recycling"
        ScrollViewer.CanContentScroll="True"
        VirtualizingPanel.ScrollUnit="Pixel"
        ItemsSource="{Binding Values}"><!-- IList<Person> -->
        <TreeView.ItemTemplate><!-- Template for first layer, which has a HierarchicalDataTemplate so that this layer will expand -->
            <HierarchicalDataTemplate
                ItemsSource="{Binding Expenses}"><!-- IList<Expense> -->
                <HierarchicalDataTemplate.ItemTemplate><!-- Template for the second layer, which has a DataTemplate instead of HierarchicalDataTemplate so that this layer won't expand -->
                    <DataTemplate>
                        <TextBlock Text="{Binding Amount}"/><!-- Expense amount in dollars -->
                    </DataTemplate>
                </HierarchicalDataTemplate.ItemTemplate>

                <TextBlock Text="{Binding Name}"/><!-- Person name -->
            </HierarchicalDataTemplate>
        </TreeView.ItemTemplate>
    </TreeView>
</Page>

The Person class:

public class Person
{
    public string Name { get; set; }
    public List<Expense> Expenses { get; set; }
}

The Expense class:

public class Expense
{
    public double Amount { get; set; }
}

Here's how it looks:

Screenshot of the above code in action

I inspected it with Snoop to prove that it is UI Virtualizing. Here's the number of loaded TreeViewItems when the app is small:

Screenshot showing the number of elements when the app is small

...And here's the number of loaded TreeViewItems when the app is fullscreen (it keeps going beyond this snippet, but you get the idea):

Screenshot showing that there are more elements when the app is fullscreen

Now it's just the simple matter of styling things to make the nested layer look how I want!

Edit: I just verified that the TreeView virtualizes all its layers, not just the first layer.

唱一曲作罢 2024-08-06 03:53:04

我有一个链接,指向不要对虚拟化堆栈面板执行哪些操作的列表,但由于某种原因,该页面显示为空白。 这是另一个对此进行了一些讨论的页面:

http ://www.designerwpf.com/2008/02/12/listview-and-listbox-performance-issues/

甚至链接到我正在谈论的那个,但它总是空白。 如果您查看该页面,则会看到 Mark Shumer 博客的链接。 如果您想尝试一下,请点击以下链接:

http ://itknowledgeexchange.techtarget.com/wpf/listview-is-it-really-too-slow/

Bea Stollnitz 也有一些相关文章可能会有所帮助:

第 1 部分
第 2 部分
第 3 部分

如果您发布一些代码,有人可能能够解开意大利面条一点可以帮助您获得更好的实施。

编辑:找到一个可能有效的链接(谢谢 archive.org!!!):
http://web.archive.org/web/20080104163725/http://itknowledgeexchange.techtarget.com/wpf/listview-is-it-really-too-slow/

I had a link to a list of what not to do with a virtualizing stackpanel, but for some reason the page comes up blank. Here's another page that talks a little about it:

http://www.designerwpf.com/2008/02/12/listview-and-listbox-performance-issues/

and even links to the one im talking about, but its always blank. if you look on that page its the link to Mark Shurmer's blog. Here's the link if you'd like to try it:

http://itknowledgeexchange.techtarget.com/wpf/listview-is-it-really-too-slow/

Bea Stollnitz also has some articles on it that might help:

Part 1
Part 2
Part 3

If you post some of your code, someone might be able to unravel the spaghetti a bit to help you get to a better implementation.

EDIT: Found a link that might work (thank you archive.org!!!):
http://web.archive.org/web/20080104163725/http://itknowledgeexchange.techtarget.com/wpf/listview-is-it-really-too-slow/

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文