嵌套ItemsControl的大量性能问题

时间:2013-07-19 09:17:57

标签: wpf itemscontrol

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

生成Demo-Data并将其绑定到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>

1 个答案:

答案 0 :(得分:0)

将以下属性添加到您的所有ItemsControl(根和嵌套的):

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