ItemsControl не виртуализируется - PullRequest
0 голосов
/ 25 марта 2019

Я не могу заставить это ItemsControl правильно виртуализироваться. Отладка показывает, что коллекция инициализируется быстро, но все элементы добавляются в элемент управления вместо подмножества (я просто помещаю TracePoint в TextBox_Initialize event in the UserControl`, который составляет элемент).

Примечание. Я рассматривал другие похожие вопросы, но не смог решить эту проблему с помощью этих ответов.

Модель представления:

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>

1 Ответ

1 голос
/ 25 марта 2019

Вероятно, это связано с использованием вами группирования. По умолчанию включение группировки эффективно отключает виртуализацию. Однако, начиная с .NET 4.5, вы сможете восстановить эту функцию через свойство VirtualizingPanel.IsVirtualizingWhenGrouping.

Выдержка из этого сообщения в блоге об улучшениях WPF в .NET 4.5:

В WPF 4.0 вы потеряли виртуализацию при группировке по отображаемой коллекции. Я повторяю: Группировка = нет виртуализации в WPF 4.0. Это по-прежнему поведение по умолчанию в WPF 4.5, , но вы можете включить виртуализацию, используя IsVirtualizingWhenGrouping присоединенное свойство VirtualizingPanel класс . Когда это будет сделано, вы сможете воспользоваться всеми уже описанными преимуществами виртуализации.

Вот как вы можете включить его через 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" вместе с другими вашими свойствами, связанными с виртуализацией, должна дать вам желаемое поведение. +

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...