سؤال

I've a performance problem with an ItemsControl. I've virtualized the ItemsControl using the following style

<Style x:Key="VirtualizedItemsControl"
       TargetType="{x:Type ItemsControl}">
    <Setter Property="VirtualizingStackPanel.IsVirtualizing"
            Value="True" />
    <Setter Property="ScrollViewer.CanContentScroll"
            Value="True" />
    <Setter Property="Template">
        <Setter.Value>
            <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>
        </Setter.Value>
    </Setter>
    <Setter Property="ItemsPanel">
        <Setter.Value>
            <ItemsPanelTemplate>
                <VirtualizingStackPanel />
            </ItemsPanelTemplate>
        </Setter.Value>
    </Setter>
</Style>

My ItemsTemplate is an Expander with another ItemsControl which ItemsTemplate is an Expander with a DataGrid (DataContext is a list in a list). example

When my bound data is getting more (like 100 entries in the first list and in each datagrid ~100 entries) the ui is getting really slow if i start to scroll. I don't know why it's getting so slow.

I change the background color of each DataGrid cell if there are changes. That's why I use DataGridTemplateColumns.

<ItemsControl ItemsSource="{Binding MyList}"
          x:Name="_container"
          Style="{StaticResource VirtualizedItemsControl}">
                <ItemsControl.ItemTemplate>
                    <DataTemplate>
                        <Expander>
                            <Expander.Header>
                                <Grid>
                                    <Grid.ColumnDefinitions>
                                        <ColumnDefinition />
                                        <ColumnDefinition Width="Auto" />
                                    </Grid.ColumnDefinitions>
                                    <TextBlock />

                                    <Button Grid.Column="1"
                                            Command="{Binding RelativeSource={RelativeSource AncestorType=UserControl}, Path=DataContext.DeleteCommand}"
                                            CommandParameter="{Binding}">
                                        <Image Source="trashcan-delete.png"
                                               HorizontalAlignment="Right" />
                                    </Button>
                                </Grid>
                            </Expander.Header>
                            <Grid>
                                <Grid.RowDefinitions>
                                    <RowDefinition Height="Auto" />
                                    <RowDefinition Height="Auto" />
                                    <RowDefinition Height="Auto" />
                                </Grid.RowDefinitions>

                                <Grid Margin="5">
                                    <Grid.ColumnDefinitions>
                                        <ColumnDefinition Width="Auto" />
                                        <ColumnDefinition />
                                    </Grid.ColumnDefinitions>

                                    <Label Content="Some text" />
                                    <ComboBox Grid.Column="1"
                                              Margin="5 0"
                                              Width="150"
                                              HorizontalAlignment="Left"
                                              Text="{Binding Name.Property}"
                                              SelectedItem="{Binding SelectedName, UpdateSourceTrigger=PropertyChanged}"
                                              Foreground="Black"
                                              IsEditable="True"
                                              DisplayMemberPath="Name"
                                              ItemsSource="{Binding RelativeSource={RelativeSource AncestorType=UserControl}, Path=DataContext.Children}"
                                              Background="{Binding Name.IsDirty, Converter={StaticResource IsDirtyToColorConverter}}" />
                                </Grid>

                                <ItemsControl Grid.Row="1"
                                              ItemsSource="{Binding ParameterBlocks}"
                                              Style="{StaticResource VirtualizedItemsControl}">
                                    <ItemsControl.ItemTemplate>
                                        <DataTemplate>
                                            <Expander>
                                                <Expander.Header>
                                                    <Grid>
                                                        <Grid.ColumnDefinitions>
                                                            <ColumnDefinition />
                                                            <ColumnDefinition Width="Auto" />
                                                        </Grid.ColumnDefinitions>
                                                        <TextBlock Text="{Binding Index, Converter={StaticResource NumberToBlockHeaderConverter}}"
                                                                   FontWeight="Bold"
                                                                   Foreground="White" />

                                                        <Button Grid.Column="1"
                                                                Command="{Binding RelativeSource={RelativeSource AncestorType=Expander, AncestorLevel=2}, Path=DataContext.DeleteBlockCommand}"
                                                                CommandParameter="{Binding}">
                                                            <Image Source="trashcan-delete.png"
                                                                   HorizontalAlignment="Right" />
                                                        </Button>
                                                    </Grid>
                                                </Expander.Header>
                                                <Grid Background="#E5E5E5">
                                                    <Grid.RowDefinitions>
                                                        <RowDefinition Height="Auto" />
                                                        <RowDefinition Height="Auto" />
                                                        <RowDefinition Height="Auto" />
                                                    </Grid.RowDefinitions>

                                                    <Grid Margin="5">
                                                        <Grid.ColumnDefinitions>
                                                            <ColumnDefinition Width="Auto" />
                                                            <ColumnDefinition Width="Auto" />
                                                            <ColumnDefinition Width="Auto" />
                                                        </Grid.ColumnDefinitions>
                                                        <CheckBox Grid.Column="0"
                                                                  Content="Some text"
                                                                  VerticalAlignment="Center"
                                                                  IsChecked="{Binding IsWaitingEnabled.Property}"
                                                                  Background="{Binding IsWaitingEnabled.IsDirty, Converter={StaticResource IsDirtyToColorConverter}}">

                                                        <Label Grid.Column="1"
                                                               Margin="15 0 0 0"
                                                               VerticalAlignment="Center"
                                                               Content="Some text"
                                                               IsEnabled="{Binding IsWaitingEnabled.Property}" />

                                                        <Xctk:IntegerUpDown Grid.Column="2"
                                                                            Minimum="0"
                                                                            Width="60"
                                                                            Margin="5 0 0 0"
                                                                            HorizontalAlignment="Left"
                                                                            Text="Some text"
                                                                            IsEnabled="{Binding IsWaitingEnabled.Property}"
                                                    </Grid>

                                                    <DataGrid ItemsSource="{Binding Channels}"
                                                              Style="{StaticResource StandardGridStyle}"
                                                              x:Name="BlockGrid"
                                                              Grid.Row="1"
                                                              CanUserSortColumns="True"
                                                              Margin="5 0"
                                                              MaxHeight="200"
                                                              SelectedItem="{Binding SelectedEntry}"
                                                              CanUserAddRows="True">
                                                        <DataGrid.Columns>
                                                            <DataGridTemplateColumn Header="Some text"
                                                                                    Width="200">
                                                                <DataGridTemplateColumn.CellTemplate>
                                                                    <DataTemplate>
                                                                        <TextBlock Text="{Binding Channel.Property, UpdateSourceTrigger=PropertyChanged}"
                                                                                   Foreground="Black"
                                                                                   Background="{Binding Channel.IsDirty, Converter={StaticResource IsDirtyToColorConverter}}" />
                                                                    </DataTemplate>
                                                                </DataGridTemplateColumn.CellTemplate>
                                                                <DataGridTemplateColumn.CellEditingTemplate>
                                                                    <DataTemplate>
                                                                        <ComboBox Text="{Binding Channel.Property, UpdateSourceTrigger=PropertyChanged}"
                                                                                  Foreground="Black"
                                                                                  IsEditable="True"
                                                                                  ItemsSource="{Binding RelativeSource={RelativeSource AncestorType={x:Type Expander}, AncestorLevel=2}, Path=DataContext.SelectedChannelList.Channels}"
                                                                                  IsEnabled="{Binding RelativeSource={RelativeSource AncestorType={x:Type UserControl}}, Path=DataContext.IsPasswordProtected, Converter={StaticResource BoolToOppositeBoolConverter}}"
                                                                                  Background="{Binding Channel.IsDirty, Converter={StaticResource IsDirtyToColorConverter}}" />
                                                                    </DataTemplate>
                                                                </DataGridTemplateColumn.CellEditingTemplate>
                                                            </DataGridTemplateColumn>

                                                            <DataGridTextColumn Header="Some text"
                                                                                Width="150"
                                                                                Foreground="Black"
                                                                                Binding="{Binding Value.Property, UpdateSourceTrigger=PropertyChanged}">
                                                                <DataGridTextColumn.ElementStyle>
                                                                    <Style TargetType="{x:Type TextBlock}">
                                                                        <Style.Triggers>
                                                                            <DataTrigger Binding="{Binding Value.IsDirty}"
                                                                                         Value="true">
                                                                                <Setter Property="Background"
                                                                                        Value="#FFDDA203" />
                                                                            </DataTrigger>

                                                                        </Style.Triggers>
                                                                    </Style>
                                                                </DataGridTextColumn.ElementStyle>
                                                            </DataGridTextColumn>

                                                            <DataGridTemplateColumn Header="Some text">
                                                                <DataGridTemplateColumn.CellTemplate>
                                                                    <DataTemplate>
                                                                        <TextBlock Text="{Binding Block.Property}"
                                                                                   Foreground="Black"
                                                                                   Background="{Binding Block.IsDirty, Converter={StaticResource IsDirtyToColorConverter}}" />
                                                                    </DataTemplate>
                                                                </DataGridTemplateColumn.CellTemplate>
                                                                <DataGridTemplateColumn.CellEditingTemplate>
                                                                    <DataTemplate>
                                                                        <Xctk:IntegerUpDown Minimum="1"
                                                                                            Maximum="{Binding RelativeSource={RelativeSource AncestorType={x:Type Expander}, AncestorLevel=2}, Path=DataContext.ParameterBlocks, Converter={StaticResource ListToCountConverter}}"
                                                                                            Text="{Binding Block.Property, UpdateSourceTrigger=PropertyChanged}"
                                                                                            Background="{Binding Block.IsDirty, Converter={StaticResource IsDirtyToColorConverter}}">
                                                                            <I:Interaction.Triggers>
                                                                                <I:EventTrigger EventName="ValueChanged">
                                                                                    <Commands:EventToCommand Command="{Binding RelativeSource={RelativeSource AncestorType={x:Type Expander}, AncestorLevel=2}, Path=DataContext.BlockChangedCommand}"
                                                                                                             CommandParameter="{Binding }" />
                                                                                </I:EventTrigger>
                                                                            </I:Interaction.Triggers>
                                                                        </Xctk:IntegerUpDown>
                                                                    </DataTemplate>
                                                                </DataGridTemplateColumn.CellEditingTemplate>
                                                            </DataGridTemplateColumn>
                                                        </DataGrid.Columns>
                                                        <I:Interaction.Behaviors>
                                                            <Commands:DataGridScrollToSelectedItemBehavior />
                                                        </I:Interaction.Behaviors>
                                                    </DataGrid>

                                                    <StackPanel Grid.Row="2"
                                                                Margin="5"
                                                                Orientation="Horizontal"
                                                                HorizontalAlignment="Right">

                                                        <Button Command="{Binding DeleteEntryCommand}"
                                                                Content="Some text"
                                                                CommandParameter="{Binding  ElementName=BlockGrid, Path=SelectedItems}"
                                                                Width="120"
                                                                Margin="5 0" />

                                                        <Button Content="Some text"
                                                                Command="{Binding AddEntryCommand}"
                                                                Width="120"
                                                                Margin="5 0"
                                                                HorizontalAlignment="Right" />
                                                    </StackPanel>
                                                </Grid>
                                            </Expander>
                                        </DataTemplate>
                                    </ItemsControl.ItemTemplate>
                                </ItemsControl>
هل كانت مفيدة؟

المحلول

Done; see my last comment. The Expander style was making some trouble.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top