我有大约45个相当大的图像(大约680x1000),需要加载到一个简单的用户控件(带有填充,图像,文本块和2个侧面矩形的圆形后边框)中,然后显示在一个wrappanel中。虚拟化在这里确实没有用,因为图像在程序加载时都是可见的。
我知道在BitmapImage init里面我可以设置decodepixel宽度,这确实有点帮助,但是我喜欢将它们全部加载为全尺寸,因为我希望能够使用滑块调整图像大小而不会丢失质量(这部分工作速度很快)。我知道有一种可能性就是将decodewidth设置为某个数字,我设置为最大可视大小可以帮助。
我尝试了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>
更新
我最终通过在单个后台工作程序中运行load image循环来使其响应更快。加载每个图像后,调用Dispacher.Invoke以创建包装项。在玩了一段时间后,我得到了它,以显示它在同一时间创建的每个项目。
答案 0 :(得分:1)
如果您对整体性能感到满意,只需加载图片,就可以试试this Multithreaded UI tutorial.我设法让它很容易上手,但是如果您在循环中加载所有图片在您加载完所有图像之前,它不会更新视觉效果。然而,UI在此期间是响应的,因为所有加载都在一个单独的线程上。
另外,如果您在循环中加载所有图像,则可以尝试improved version of Windows Forms DoEvents method(向下滚动到示例)。您在加载每个图像后调用它,它将为UI提供更新自身的机会(处理用户交互等)。这是我为项目加载地图图块时使用的方法,比第一个更容易。