WPF虚拟化大项目

时间:2011-04-04 11:57:04

标签: wpf virtualization itemscontrol

我将一个非常庞大的项目集合绑定到ItemsControl。 ItemsControl的ItemTemplate设置为呈现数据的自定义用户控件。 ItemControl已虚拟化。

现在的问题是ItemsControl中的每个用户控件都会变得非常高。甚至可能它变得比实际的屏幕高度更高。如果发生这种情况我就没有机会看到其余的用户控件,因为只要我滚动集合中的下一个项目就会被带到屏幕的顶部,并且只有一半显示的项目会完全滚动到视图之外。如果我不使用虚拟化,一切都显然正常。

有没有办法绕过这种行为并仍能使用虚拟化?

2 个答案:

答案 0 :(得分:1)

您的ItemsControl的ScrollViewer是否具有内容滚动设置?

编辑2:正如Dan所说,只要你试图顺利滚动就会出现,你就会失去虚拟化。我不确定您的要求是什么,但潜在的解决方法可能类似于以下内容:

<Window x:Class="TestApp11.MainWindow" 
    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"
        mc:Ignorable="d"
    xmlns:l="clr-namespace:TestApp11"
    Title="Window1" Height="200" Width="200">
    <Grid>
        <ItemsControl>
            <ItemsControl.Template>
                <ControlTemplate>
                    <ScrollViewer CanContentScroll="True" VirtualizingStackPanel.IsVirtualizing="True" VirtualizingStackPanel.VirtualizationMode="Recycling">
                        <ItemsPresenter />
                    </ScrollViewer>
                </ControlTemplate>
            </ItemsControl.Template>
            <ItemsControl.ItemTemplate>
                <DataTemplate DataType="{x:Type ListBoxItem}">
                    <ScrollViewer ScrollViewer.VerticalScrollBarVisibility="Auto" MaxHeight="160">
                        <Border Height="200" Width="140" BorderBrush="Red" BorderThickness="10" Margin="1" Background="Blue" />
                    </ScrollViewer>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
            <ItemsControl.ItemsPanel>
                <ItemsPanelTemplate>
                    <VirtualizingStackPanel VirtualizingStackPanel.VirtualizationMode="Recycling" />
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>
            <ContentElement />
            <ContentElement />
            <ContentElement />
            <ContentElement />
            <ContentElement />
            <ContentElement />
            <ContentElement />
            <ContentElement />
            <ContentElement />
            <ContentElement />
            <ContentElement />
            <ContentElement />
            <ContentElement />
            <ContentElement />
            <ContentElement />
            <ContentElement />
            <ContentElement />
        </ItemsControl>
    </Grid>
</Window>

基本上,您可以让ItemTemplate将您的UserControl项包装在ScrollViewer中。我没有在我的示例中显示它,但是您可以将ScrollViewer的MaxHeight(在ItemTemplate内)绑定到可视区域的高度,然后只有当UserControl太大而不能显示时,垂直滚动条才会显示适合屏幕。

我可以看到这可能是一个太难看的解决方案给客户,但在这种情况下,我认为唯一的选择是走丹建议的路线。

答案 1 :(得分:1)

这种行为有一种方法,但它并不完全相当......基本上,它是实现自己的虚拟化面板。正如您所注意到的,内置面板的行为是从最顶层项目的顶部绘制 - 您不能在屏幕顶部有半个项目。这基本上是因为它使虚拟化代码的重量更轻,而且在大多数情况下它不是问题。

您可以创建自己的面板(源自VirtualizingPanel),但没有此限制。这不是直截了当的,但结果是值得的!

在您的情况下,如果所有项目都是固定大小且超出屏幕大小,您可能会发现它并不那么复杂 - 当项目变量大小时会出现很多复杂性