C# 滚动多个虚拟化项控件

C# 滚动多个虚拟化项控件,c#,wpf,C#,Wpf,我有一个类似日历的控件,一周中的每一天都有一列和七个可观察的集合,每个集合最多可以包含100个或更多项 我希望能够在虚拟化它们的同时垂直滚动它们[Edit] 现在我有以下的布局 <ScrollViewer> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="1*"></ColumnDefinition>

我有一个类似日历的控件,一周中的每一天都有一列和七个可观察的集合,每个集合最多可以包含100个或更多项

我希望能够在虚拟化它们的同时垂直滚动它们[Edit]

现在我有以下的布局

<ScrollViewer>
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="1*"></ColumnDefinition>
            <ColumnDefinition Width="1*"></ColumnDefinition>
            <ColumnDefinition Width="1*"></ColumnDefinition>
            <ColumnDefinition Width="1*"></ColumnDefinition>
            <ColumnDefinition Width="1*"></ColumnDefinition>
            <ColumnDefinition Width="1*"></ColumnDefinition>
            <ColumnDefinition Width="1*"></ColumnDefinition>
        </Grid.ColumnDefinitions>

        <!-- Monday -->
        <Border Grid.Column="0">
            <ItemsControl ItemsSource="{Binding Monday}">
                <ItemsControl.ItemsPanel>
                    <ItemsPanelTemplate>
                        <VirtualizingStackPanel IsVirtualizing="True" VirtualizationMode="Recycling" ... />
                    </ItemsPanelTemplate>
                </ItemsControl.ItemsPanel>
                <ItemsControl.ItemTemplate>
                    <DataTemplate>
                        <MyControl Item="{Binding}" ... />
                    </DataTemplate>
                </ItemsControl.ItemTemplate>
            </ItemsControl>
        </Border>

        ...

    </Grid>
</ScrollViewer>

...
然而,性能是有问题的,我认为这是因为ScrollViewer允许网格->边框->虚拟化StackPanel垂直扩展,而不是虚拟化。是这样吗

(旁注:我已尝试删除ScrollViewer并将CanVerticallyScroll=“True”添加到VirtualzingStackPanels,并希望它们独立滚动以检查性能是否更好,但它们根本不会滚动)

什么是正确的布局

编辑:每列显示100个元素(总共700个)需要13秒,滚动实际上是可以的

[Edit2]
由于需要同时滚动,我尝试创建一个包含“一行”(7项)的新集合,并将其作为listview中的模板。可怕的结果[/Edit2]

要使ItemsControl虚拟化,您不仅需要使用VirtualzingStackPanel,还需要将ScrollViewer添加到ItemsControl的模板中(通常ItemsControl没有ScrollViewer)

将此模板添加到ItemsControl中:

<ItemsControl.Template>
    <ControlTemplate>
        <Border BorderThickness="{TemplateBinding Border.BorderThickness}"
                Padding="{TemplateBinding Control.Padding}"
                BorderBrush="{TemplateBinding Border.BorderBrush}"
                Background="{TemplateBinding Panel.Background}"
                SnapsToDevicePixels="True">
            <ScrollViewer Padding="{TemplateBinding Control.Padding}"
                          Focusable="False">
                <ItemsPresenter SnapsToDevicePixels="{TemplateBinding UIElement.SnapsToDevicePixels}" />
            </ScrollViewer>
        </Border>
    </ControlTemplate>
</ItemsControl.Template>


作为一种不同的解决方案,您当然可以用ListBox替换ItemsControl,它已经具备了虚拟化列表所需的所有功能。

解决此问题的方法是在ScrollViewer中不使用一个虚拟化ItemsControl呈现七列(这似乎扩展了ItemsControl并使其绘制所有控件),但使用一个ItemsControl进行渲染,解决了在ItemsControl.Template中滚动的问题,并一次显示一行

我创建了一个新集合,并“每行”抓取对象

for(int PI=0;PIPI?Monday[PI]:空,
星期二。计数>π?星期二[π]:空,
星期三.计数>PI?星期三[PI]:空,
星期四.Count>PI?星期四[PI]:空,
Friday.Count>PI?Friday[PI]:空,
星期六.计数>圆周率?星期六[圆周率]:空,
Sunday.Count>PI?Sunday[PI]:空
));
}
并使用此

<ItemsControl ItemsSource="{Binding Presentation}" VirtualizingPanel.ScrollUnit="Pixel">
    <ItemsControl.Template>
        <ControlTemplate>
            <ScrollViewer CanContentScroll="True" Focusable="False">
                <ItemsPresenter />
            </ScrollViewer>
        </ControlTemplate>
    </ItemsControl.Template>
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <VirtualizingStackPanel 
                Orientation="Vertical" 
                IsVirtualizing="True"
                VirtualizationMode="Recycling">
            </VirtualizingStackPanel>
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="*"/>
                    <ColumnDefinition Width="*"/>
                    <ColumnDefinition Width="*"/>
                    <ColumnDefinition Width="*"/>
                    <ColumnDefinition Width="*"/>
                    <ColumnDefinition Width="*"/>
                    <ColumnDefinition Width="*"/>
                </Grid.ColumnDefinitions>

                <MyControl Item="{Binding Monday}" Grid.Column="0" ... />

                ...

            </Grid>
        </DataTemplate>
    </ItemsControl.ItemTemplate
</ItemsControl>

...

希望您有充分的理由使用自定义控件,通常您可以使用
DataTemplate
来代替。我认为延迟可能是由于复杂的模板造成的,但我们看不到这一点,所以这只是一个猜测。@XAMlMAX感谢您的输入!基本上是因为该控件可能在其他地方被重用。pu的好处可能在哪里它的内容是否直接在datatemplate中?理想情况下,您可以在资源字典中将其定义为静态资源,然后在您需要的地方在xaml中引用它。App.xaml将是一个完美的起点。我会检查这是否有可能,但我在它后面有540行代码。您是指
C#
code还是JUxaml?如果你有代码隐藏,那么可能有一个很好的理由,出于好奇,为什么你有代码隐藏?谢谢!这个例子中的VirtualzingStackPanel在哪里?这会导致列独立滚动,而不是同时滚动,对吗?这不是全部代码,只是你需要在it中添加的部分emsControl。是的,这将使每个列独立滚动。好的,谢谢,很遗憾这不是我想要实现的,同时滚动是必须的。我想我可以让其他人跟随,但他们会在最后停止,而其他人继续滚动
<ItemsControl ItemsSource="{Binding Presentation}" VirtualizingPanel.ScrollUnit="Pixel">
    <ItemsControl.Template>
        <ControlTemplate>
            <ScrollViewer CanContentScroll="True" Focusable="False">
                <ItemsPresenter />
            </ScrollViewer>
        </ControlTemplate>
    </ItemsControl.Template>
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <VirtualizingStackPanel 
                Orientation="Vertical" 
                IsVirtualizing="True"
                VirtualizationMode="Recycling">
            </VirtualizingStackPanel>
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="*"/>
                    <ColumnDefinition Width="*"/>
                    <ColumnDefinition Width="*"/>
                    <ColumnDefinition Width="*"/>
                    <ColumnDefinition Width="*"/>
                    <ColumnDefinition Width="*"/>
                    <ColumnDefinition Width="*"/>
                </Grid.ColumnDefinitions>

                <MyControl Item="{Binding Monday}" Grid.Column="0" ... />

                ...

            </Grid>
        </DataTemplate>
    </ItemsControl.ItemTemplate
</ItemsControl>