2010-06-30 581 views
6

我有大约45张体积很大的图像(大约680x1000)需要加载到一个简单的用户控件(带填充,图像,文本块和2边矩形的圆形边框)中,然后显示在一个包装中。由于图像在程序加载时全部可见,因此虚拟化对此不会有帮助。WPF:如何快速将大量大图片加载到wrappanel中?

我知道里面的BitmapImage初始化我可以设置decodepixel宽度,这有一点帮助,但是id喜欢加载它们全部作为全尺寸,因为我想能够调整图像的大小而不会丢失质量(这部分大部分工作很快)。我知道一种可能性是将解码宽度设置为我设置的最大可视大小可以帮助的某个数字。

我尝试了在How do I load images in the background?(第一个答案)中找到的多线程方法,但它导致程序花费很长的时间来加载!

任何想法?

电流负载代码:

BitmapImage bmp = new BitmapImage(); 
bmp.BeginInit(); 
//bmp.DecodePixelWidth = 400; 
bmp.UriSource = new Uri(file.FullName); 
bmp.EndInit(); 
bmp.Freeze(); 
images.Add(bmp); 

样品XAML代码:

 <Border x:Name="backBorder" Background="Black" Padding="2" Margin="3" CornerRadius="3,3,4,4" 
      BorderBrush="Black" BorderThickness="1" 
      MouseEnter="backBorder_MouseEnter" MouseLeave="backBorder_MouseLeave" MouseLeftButtonUp="backBorder_MouseLeftButtonUp" > 
    <Grid> 
     <Grid.RowDefinitions> 
      <RowDefinition /> 
      <RowDefinition Height="16" /> 
     </Grid.RowDefinitions> 
     <Grid.ColumnDefinitions> 
      <ColumnDefinition /> 
      <ColumnDefinition Width="15" /> 
     </Grid.ColumnDefinitions> 
     <Image x:Name="imageBox" Stretch="Fill" Width="{Binding Path=ImageWidth, ElementName=me}" Height="{Binding Path=ImageHeight, ElementName=me}" /> 
     <Border x:Name="backRatingBorder" Grid.Column="1" Margin="3,0,0,0" BorderBrush="Blue" Background="White" BorderThickness="1"/> 
     <Border x:Name="frontRatingBorder" Grid.Column="1" Margin="3,0,0,0" BorderBrush="Blue" Background="LightBlue" BorderThickness="1" VerticalAlignment="Bottom" Height="50"/> 
     <TextBlock x:Name="textBlock" Grid.Row="1" Grid.ColumnSpan="2" TextAlignment="Center" Background="Transparent" Foreground="White" FontFamily="Segoe UI" FontWeight="SemiBold" FontSize="12" /> 
    </Grid> 
</Border> 

UPDATE:

嗯,我最终作出通过运行在一个单一的后台工作负载图像循环更加适应。每个图像加载后,调用Dispacher.Invoke来创建换行项目。玩了一段时间后,我得到它显示每个项目,因为它是在以前的同一时间创建的。

回答

1

如果您对整体性能感到满意,只需加载图像,就可以尝试this Multithreaded UI tutorial.我设法让它很容易地工作,但如果您将所有图像加载到循环中, t更新视觉效果,直到完成加载所有图像。然而,UI在这段时间内是有响应的,因为所有的加载都在一个单独的线程上。

或者,如果您要将所有图像加载到循环中,则可以尝试improved version of Windows Forms DoEvents method(向下滚动至示例)。你可以在加载完每个图像后调用它,它会让UI有机会更新自己(处理用户交互等)。这是我为我的项目加载地图图块时使用的方法,比第一个方法更简单。

+1

我认为我的主要问题是从磁盘到内存的实际加载的图像。我不确定是否有什么我可以在这里修复的,是吗?我将所有图像加载到一个列表中,然后生成所有包含列表中对BitmapImages的引用的换行项目。我可以清除所有包装儿童并重新创建它们,但装载本身需要几秒钟的时间。我尝试了一个Parallel.For循环来将图像加载到列表中,但它导致它们加载速度较慢,可能是由于异步磁盘访问。 – user380527 2010-07-01 04:04:18