0

我无法ItemsControl让它正确虚拟化。调试显示集合被快速初始化,但所有项目都被添加到控件而不是子集(我只是在组成项目的 TextBox_Initialize event in theUserControl` 中放置了一个 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>

4

1 回答 1

2

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

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

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

以下是通过 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"其他与虚拟化相关的属性应该会给你你想要的行为。+

于 2019-03-25T13:05:54.817 回答