在WPF中将嵌套容器(virtualizingstackpanel)虚拟化为单个父滚动条 [英] virtualizing nested containers (virtualizingstackpanel) to a single parent scrollbar in WPF

查看:141
本文介绍了在WPF中将嵌套容器(virtualizingstackpanel)虚拟化为单个父滚动条的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经把自己编码成泡菜了.我正在编写类似于TreeListView的自定义WPF控件. 这篇MSDN文章>这篇MSDN文章以及网络上的许多其他地方.在这一点上,很多事情都是自定义的,除了虚拟化方面,它已经很好地满足了我的目标.我覆盖的TreeViewTreeViewItem模板都使用VirtualizingStackPanel来显示其项目,并且我已验证所有这些都已按预期创建.虚拟化可以在根级项目上正常运行(仅准备了ScrollViewer中当前可见的UI元素),并且TreeView内容可确保不为折叠节点生成元素.问题是在扩展节点时出现的-节点中每个孩子的所有元素都准备好了,甚至是屏幕外的数千个.

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.

在我看来,我所需要做的就是以某种方式将内部嵌套的VirtualizingStackPanel的scrollowner属性设置为与根级VSP默认挂钩的同一主滚动视图,但是我读了MSFT海报这里说这是行不通的.

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.

推荐答案

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

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

在我的情况下,我认为TreeView不会削减它,因为我恰好需要两层,并且显示的项目类型在这两层之间是不同的.另外,我正在重构Expander的列表,所以我在进行更多的一维思考.

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.

但是后来我意识到,您可以自定义TreeViewItemTemplate以包括您自己的HierarchicalDataTemplate,并且可以使用自己定制的DataTemplate来自定义HierarchicalDataTemplateItemTemplate. .. Presto!恰好是两层,每一层都有不同的东西!

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!

所以我的意思是TreeView足够灵活,您应该尝试不要创建自己的自定义控件.

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

这就是我所做的:

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; }
}

这是它的外观:

我使用 Snoop 进行了检查,以证明它是UI虚拟化的.这是应用较小时已加载的TreeViewItem的数量:

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

...这是应用全屏显示时已加载的TreeViewItem的数量(它不断超出此代码段,但您知道了):

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

现在,只需简单地设置样式即可使嵌套图层看起来像我想要的样子!

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

我刚刚验证了TreeView虚拟化了其所有层,而不仅仅是第一层.

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

这篇关于在WPF中将嵌套容器(virtualizingstackpanel)虚拟化为单个父滚动条的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆