嵌套ItemsControl的大量性能问题 [英] Massive performance issue with nested ItemsControl

查看:43
本文介绍了嵌套ItemsControl的大量性能问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用嵌套的ItemsControl来显示分层数据.问题是,即使只有很少的数据,这也非常慢.它还会完全阻塞UI-Thread,直到加载数据为止.我在这里做错什么了?

I use a nested ItemsControl to display hierarchical data. Problem is that this is terribly slow even with little data. Its also blocking the UI-Thread completely until data is loaded. What am I doing wrong here?

用于生成演示数据并将其绑定到ItemsControl的代码:

Code to generate Demo-Data and bind it to the ItemsControl:

private void SetupDemodata()
    {
        ObservableCollection<Folder> demoData = new ObservableCollection<Folder>();

        const int numberOfFolders = 1;
        const int numberOfFiles = 1;
        const int numberOfLines = 300;

        Random randContentLength = new Random();


        for( int indexFolders = 0; indexFolders <= numberOfFolders; indexFolders++ )
        {
            Folder newFolder = new Folder {FolderName = string.Format( "DemoFolder {0}", indexFolders )};

            for( int indexFiles = 0; indexFiles <= numberOfFiles; indexFiles++ )
            {
                File newFile = new File {FileName = string.Format( "DemoFile {0} -> {1}", indexFolders, indexFiles )};


                for( int indexLines = 0; indexLines <= numberOfLines; indexLines++ )
                {
                    newFile.ContentLines.Add( new FileContentLine
                        {
                            LineContent = GetRandomString( randContentLength.Next( 80 ) ),
                            LineNumber = indexLines
                        } );
                }
                newFolder.Files.Add( newFile );
            }
            demoData.Add( newFolder );
        }

        this.icFolders.ItemsSource = demoData;
    }

    private static readonly Random random = new Random();
    private static string GetRandomString(int length )
    {
        length = Math.Max( length, 3 );
        byte[] bytes = new byte[length];
        random.NextBytes( bytes );
        return Convert.ToBase64String( bytes ).Substring( 0, length );
    }

模型:

public class Folder
{
    public List<File> Files { get; set; }
    public string FolderName { get; set; }
    public Folder(){ this.Files = new List<File>();}
}

public class File
{
    public List<FileContentLine> ContentLines { get; set; }
    public string FileName { get; set; }
    public File() { this.ContentLines = new List<FileContentLine>(); }
}

public class FileContentLine
{
    public int LineNumber { get; set; }
    public string LineContent { get; set; }
}

还有XAML:

<Grid>
    <ScrollViewer VerticalScrollBarVisibility="Auto">
        <Grid>

            <Grid>
                <ItemsControl Grid.Row="0" x:Name="icFolders" HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch" >

                    <!-- Folder -->
                    <ItemsControl.ItemTemplate>
                        <DataTemplate DataType="{x:Type local:Folder}">
                            <Grid Margin="0">
                                <Grid.RowDefinitions>
                                    <RowDefinition Height="Auto"/>
                                    <RowDefinition Height="Auto"/>
                                    <RowDefinition Height="*"/>
                                </Grid.RowDefinitions>
                                <Border Grid.Row="0" BorderThickness="0,1,0,1" BorderBrush="#c5c5c5">
                                    <Grid Grid.Row="0" Style="{StaticResource styleGridGradient}">
                                        <Grid>
                                            <Grid.ColumnDefinitions>
                                                <ColumnDefinition Width="Auto" />
                                                <ColumnDefinition Width="*" />
                                                <ColumnDefinition Width="Auto" />
                                            </Grid.ColumnDefinitions>
                                            <Label Grid.Column="0" Style="{StaticResource styleLabelBold}" Content="{Binding FolderName}" />
                                            <Label Grid.Column="2" Style="{StaticResource styleLabelBold}" Content="{Binding Files.Count}" />
                                        </Grid>
                                    </Grid>
                                </Border>
                                <Border Grid.Row="1" BorderThickness="0,1,0,1" BorderBrush="#c5c5c5">
                                    <Grid Style="{StaticResource styleGridGradient}">
                                       <Label Foreground="#666666" 
                                       Margin="5,0,0,0" 
                                       HorizontalAlignment="Stretch" 
                                       Content="{Binding FolderName}"  />
                                    </Grid>
                                </Border>

                                <!--Files -->
                                <ItemsControl Grid.Row="2" ItemsSource="{Binding Files}" >
                                    <ItemsControl.ItemTemplate>
                                        <DataTemplate DataType="{x:Type local:File}">
                                            <Grid Margin="0">
                                                <Grid.RowDefinitions>
                                                    <RowDefinition Height="Auto" />
                                                    <RowDefinition Height="*" />
                                                </Grid.RowDefinitions>
                                                <Border Grid.Row="0" BorderThickness="0,1,0,1" BorderBrush="#c5c5c5">
                                                    <Grid Style="{StaticResource styleGridGradient}">
                                                        <Grid.ColumnDefinitions>
                                                            <ColumnDefinition Width="*"/>
                                                            <ColumnDefinition Width="Auto"/>
                                                        </Grid.ColumnDefinitions>

                                                        <Label Grid.Column="0"
                                                           Foreground="#666666"
                                                           Margin="5,0,0,0"
                                                           VerticalContentAlignment="Center"
                                                           VerticalAlignment="Center"
                                                           Content="{Binding FileName}" />

                                                        <Button Grid.Column="1" Margin="5" MaxHeight="25" Content="Open File"/>

                                                    </Grid>
                                                </Border>

                                                <!-- Lines -->
                                                <ItemsControl Grid.Row="1" ItemsSource="{Binding ContentLines}" Background="White">
                                                    <ItemsControl.ItemTemplate>
                                                        <DataTemplate DataType="{x:Type local:FileContentLine}">
                                                            <Grid Margin="0" Height="20">
                                                                <Grid.ColumnDefinitions>
                                                                    <ColumnDefinition Width="35" />
                                                                    <ColumnDefinition Width="20" />
                                                                    <ColumnDefinition Width="*" />
                                                                </Grid.ColumnDefinitions>

                                                                <Border Grid.Column="0" BorderThickness="0,0,1,0" BorderBrush="#c5c5c5">
                                                                    <ToggleButton>
                                                                        <Label Content="{Binding LineNumber}" />
                                                                    </ToggleButton>
                                                                </Border>

                                                                <Border Grid.Column="2" BorderThickness="0,0,1,0" BorderBrush="#c5c5c5">
                                                                    <Border  Grid.Column="2" BorderThickness="0,1,0,1" BorderBrush="Red">
                                                                        <Label Height="20" Content="+" HorizontalAlignment="Center" />
                                                                    </Border>
                                                                </Border>

                                                                <Border Grid.Column="3" BorderThickness="0,1,0,1" BorderBrush="Gray">
                                                                    <TextBox Height="20" IsReadOnly="True"
                                                                             VerticalAlignment="Center"
                                                                             VerticalContentAlignment="Center"
                                                                             Text="{Binding LineContent}" />
                                                                </Border>
                                                            </Grid>
                                                        </DataTemplate>
                                                    </ItemsControl.ItemTemplate>
                                                </ItemsControl>

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

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

推荐答案

将以下属性添加到所有ItemsControl(root和嵌套属性)中:

Add the following property to all your ItemsControls (root and nested ones):

<ItemsControl.ItemsPanel>
  <ItemsPanelTemplate>
     <VirtualizingStackPanel/>
  </ItemsPanelTemplate>
</ItemsControl.ItemsPanel>

这篇关于嵌套ItemsControl的大量性能问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆