2010-06-30 2 views
6

Ich habe etwa 45 anständig große Bilder (ca. 680x1000), die in ein einfaches Benutzersteuerelement geladen werden müssen (gerundetes Backborder mit Füllung, Bild, Textblock und 2 Seitenrechtecken) und dann in einem Wrapper angezeigt werden. Virtualisierung wird hier nicht wirklich helfen, da die Bilder bei Programmlast alle sichtbar sein sollen.WPF: Wie kann man viele große Bilder schnell in das Wrappel laden?

Ich weiß innerhalb der BitmapImage Init kann ich die decodepixel Breite einstellen, die ein wenig hilft, aber ID möchte sie alle als volle Größe laden, da ich die Bilder mit einem Schieberegler ändern können, ohne Qualität zu verlieren (dieser Teil arbeitet größtenteils schnell). Ich weiß, eine Möglichkeit wäre, die Dekodierungsbreite auf eine Zahl zu setzen, die ich als maximal sichtbare Größe einstellen könnte.

Ich versuchte den Multithread-Ansatz gefunden in How do I load images in the background? (erste Antwort), aber es verursacht das Programm zu viel länger zu laden!

Irgendwelche Ideen?

Strombelastung Code:

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

Beispiel XAML-Code:

 <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:

Nun, ich landete so dass es in Reaktion durch die Last Bild Schleife in einem einzigen Hintergrund Arbeiter ausgeführt wird. Nachdem jedes Bild geladen wurde, wird Dispacher.Invoke aufgerufen, um das Umbruchelement zu erstellen. Nachdem ich eine Weile damit gespielt habe, konnte ich jedes Element so anzeigen, wie es in der gleichen Zeit erstellt wurde.

Antwort

1

Wenn Sie mit der Gesamtleistung zufrieden sind, nur das Laden der Bilder, könnten Sie versuchen this Multithreaded UI tutorial. Ich schaffte es, um es recht einfach zu arbeiten, aber wenn Sie alle Bilder in einer Schleife laden, gewann es t Aktualisieren Sie das Visual, bis Sie alle Bilder geladen haben. Die Benutzeroberfläche reagiert jedoch während dieser Zeit, da sich alle Ladevorgänge in einem separaten Thread befinden.

Alternativ, wenn Sie alle Ihre Bilder in einer Schleife laden, können Sie versuchen, eine improved version of Windows Forms DoEvents method (scrollen Sie bis zum Beispiel). Sie würden dies nach dem Laden jedes Bildes aufrufen und es würde der Benutzeroberfläche die Möglichkeit geben, sich selbst zu aktualisieren (Benutzerinteraktion usw.). Dies ist der Ansatz, den ich beim Laden von Kartenkacheln für mein Projekt verwendet habe, und ist einfacher als der erste.

+1

Ich denke, mein Hauptproblem ist das tatsächliche Laden der Bilder von der Festplatte in den Speicher. Ich bin mir nicht sicher, ob es etwas gibt, das ich hier wirklich reparieren kann, oder? Ich lade alle Bilder in eine Liste, dann erzeuge ich alle Wrap-Elemente mit Verweisen auf die BitmapImages aus der Liste. Ich kann alle Wrap-Kinder löschen und sie ziemlich schnell erstellen, aber das Laden selbst dauert mehrere Sekunden. Ich habe versucht, eine Parallel.For-Schleife, um die Bilder in die Liste zu laden, aber es verursacht, dass sie viel langsamer laden, wahrscheinlich aufgrund Async-Festplattenzugriff. – user380527