J'ai environ 45 images de taille décente (environ 680x1000) qui doivent être chargées dans un contrôle utilisateur simple (backborder arrondi avec remplissage, image, bloc de texte et 2 rectangles latéraux), puis affichées dans un wrappanel. La virtualisation n'aidera pas vraiment ici car les images doivent être toutes visibles au chargement du programme. Je sais à l'intérieur de l'init BitmapImage je peux définir la largeur de décodépixel, ce qui aide un peu, mais je tiens à les charger tous en taille réelle, car je veux pouvoir redimensionner les images avec un curseur sans perte de qualité (cette partie fonctionne vite pour la plupart). Je sais qu'une possibilité serait de définir la décodeur de largeur à un certain nombre que je définis comme la taille maximale visible pourrait aider.WPF: Comment charger beaucoup de grandes images rapidement dans wrappanel?
J'ai essayé l'approche multithread trouvée dans How do I load images in the background? (première réponse), mais cela a causé beaucoup plus de temps pour charger le programme!
Des idées?
Code de charge actuel:
BitmapImage bmp = new BitmapImage();
bmp.BeginInit();
//bmp.DecodePixelWidth = 400;
bmp.UriSource = new Uri(file.FullName);
bmp.EndInit();
bmp.Freeze();
images.Add(bmp);
Exemple de code 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>
.
MISE À JOUR:
Eh bien, je fini par le rendre plus réactif en exécutant la boucle d'image de charge en un seul travailleur de fond. Une fois chaque image chargée, Dispacher.Invoke est appelée pour créer l'élément de retour à la ligne. Après avoir joué avec pendant un moment, je l'ai eu pour montrer chaque élément tel qu'il est créé dans le même temps que cela a pris auparavant.
Je pense que mon problème principal est le chargement réel des images du disque dans la mémoire. Je ne suis pas sûr s'il y a quelque chose que je peux vraiment résoudre ici, est là? Je charge toutes les images dans une liste, puis je génère tous les éléments de retour à la ligne avec des références à BitmapImages de la liste. Je peux effacer tous les enfants et les créer rapidement, mais le chargement lui-même prend plusieurs secondes. J'ai essayé une boucle Parallel.For pour charger les images dans la liste, mais cela a provoqué leur chargement beaucoup plus lent, probablement dû à l'accès au disque asynchrone. – user380527