项目控制不虚拟化



我无法正确虚拟化此ItemsControl。 调试显示集合初始化速度很快,但所有项都添加到控件中,而不是子集(我只是在构成该项的 UserControl' TextBox_Initialize event in the中放置一个 TracePoint(。

注意:我看过其他类似的问题,但无法用这些答案解决这个问题。

视图模型:

public class ImportInformationViewModel : CommandViewModel
{
    public ImportInformationViewModel()
    {
        this.PropertyChanged += ImportInformationViewModel_PropertyChanged;
    }
    private ObservableCollection<SingleTransactionViewModel> mTransactions;
    public ReadOnlyObservableCollection<SingleTransactionViewModel> Transactions
    {
        get
        {
            if (mTransactions == null)
                mTransactions = new ObservableCollection<SingleTransactionViewModel>();
            var filtered = mTransactions.Where(trans => !trans.IgnoreTransaction)
                .OrderBy(trans => trans.DateStamp)
                .ThenBy(trans => trans.TransactionName)
                .ThenBy(trans => trans.TransactionDetail);
            return new ReadOnlyObservableCollection<SingleTransactionViewModel>(new ObservableCollection<SingleTransactionViewModel>(filtered));
        }
    }
    private void ImportInformationViewModel_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
    {
        if (e.PropertyName == "TransactionFileName")
        {
            if (File.Exists(mTransactionFileName))
           {
                mTransactions.Clear();
                // Process File (Not Shown)
                mTransactions.Add(new SingleTransactionViewModel()
                {
                    DateStamp = date,
                    TransactionDetail = someText;
                });
            }
        }
        if (e.PropertyName != "Transactions")
            NotifyPropertyChanged("Transactions");
    }
}

SingleTransactionViewModel只是另一个实现INotifyPropertyChanged的类。 没什么特别的。

下面是包含ItemsControl的控件

<UserControl x:Class="ImportInformationView">
    <UserControl.Resources>
        <CollectionViewSource x:Key="TransactionsData" Source="{Binding Transactions}">
            <CollectionViewSource.GroupDescriptions>
                <PropertyGroupDescription PropertyName="YearAndMonth" />
            </CollectionViewSource.GroupDescriptions>
        </CollectionViewSource>
        <BooleanToVisibilityConverter x:Key="booleanToVisibility" />
    </UserControl.Resources>
    <ItemsControl ItemsSource="{Binding Source={StaticResource TransactionsData}}"
                        HorizontalAlignment="Stretch"
                        HorizontalContentAlignment="Stretch"
                        ScrollViewer.CanContentScroll="True"
                        VirtualizingStackPanel.IsVirtualizing="True"
                        VirtualizingStackPanel.VirtualizationMode="Recycling"
                        MinHeight="20">
            <ItemsControl.GroupStyle>
                <GroupStyle>
                    <GroupStyle.ContainerStyle>
                        <Style TargetType="{x:Type GroupItem}">
                            <Setter Property="Template">
                                <Setter.Value>
                                    <ControlTemplate TargetType="{x:Type GroupItem}">
                                        <GroupBox Padding="5" Margin="2,5">
                                            <GroupBox.Header>
                                                <Border Background="Black"
                                                        CornerRadius="4">
                                                    <TextBlock Text="{Binding Name}" />
                                                </Border>
                                            </GroupBox.Header>
                                            <ItemsPresenter />
                                        </GroupBox>
                                    </ControlTemplate>
                                </Setter.Value>
                            </Setter>
                        </Style>
                    </GroupStyle.ContainerStyle>
                </GroupStyle>
            </ItemsControl.GroupStyle>
            <ItemsControl.Template>
                <ControlTemplate>
                    <ScrollViewer CanContentScroll="True">
                        <ItemsPresenter SnapsToDevicePixels="{TemplateBinding UIElement.SnapsToDevicePixels}" />
                    </ScrollViewer>
                </ControlTemplate>
            </ItemsControl.Template>
            <ItemsControl.ItemsPanel>
                <ItemsPanelTemplate>
                    <UniformGrid IsItemsHost="True" Columns="2" Grid.IsSharedSizeScope="True" VirtualizingStackPanel.IsVirtualizing="True" />
                    <!--<VirtualizingStackPanel IsItemsHost="True" />-->
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <views:SingleTransactionView Margin="4,6" />
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>
    </UserControl>

我将SingleTransactionView归结为非常简单的事情:

    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="Auto" SharedSizeGroup="ExpanderColumn" />
        <ColumnDefinition Width="*" SharedSizeGroup="TransactionNameColumn" />
        <ColumnDefinition Width="Auto" SharedSizeGroup="DateColumn" />
        <ColumnDefinition Width="Auto" SharedSizeGroup="OptionsColumn" />
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto" />
        <RowDefinition Height="Auto" />
    </Grid.RowDefinitions>

    <TextBlock Grid.Column="1"
               Grid.Row="0"
               Initialized="TextBlock_Initialized"
               Text="{Binding TransactionName}"
               HorizontalAlignment="Left"
               VerticalAlignment="Center"
               FontSize="14"
               FontWeight="Bold"
               Margin="4"/>        
</Grid>

这可能是由于您使用了分组。 默认情况下,启用分组会有效地关闭虚拟化。 但是,从 .NET 4.5 开始,您应该能够通过 VirtualizingPanel.IsVirtualizingWhenGrouping 属性重新获得此功能。

摘自这篇关于 .NET 4.5 中的 WPF 增强功能的博客文章:

在 WPF 4.0 中,在显示的集合上完成分组时,将丢失虚拟化。我再说一遍:分组=WPF 4.0中没有虚拟化。这仍然是 WPF 4.5 的默认行为,但您可以使用 VirtualizingPanel 类的 IsVirtualizingWhenGrouping 附加属性打开虚拟化。完成此操作后,您将受益于已描述的所有虚拟化优势。

下面介绍了如何通过 XAML 启用它:

<ListBox ItemsSource="{Binding Persons}"
         ItemTemplate="{StaticResource PersonDataTemplate}"
         VirtualizingPanel.IsVirtualizing="True"
         VirtualizingPanel.IsVirtualizingWhenGrouping="True">
    <ListBox.GroupStyle>
        <GroupStyle HeaderTemplate="{StaticResource GroupHeaderTemplate}" />
    </ListBox.GroupStyle>
</ListBox>

听起来,将VirtualizingPanel.IsVirtualizingWhenGrouping="True"与其他虚拟化相关属性一起设置应该可以为您提供所需的行为。

最新更新