2010-06-30 5 views
6

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.

Répondre

1

Si vous êtes satisfait de la performance globale, juste le chargement des images, vous pouvez essayer this Multithreaded UI tutorial. J'ai réussi à le faire fonctionner assez facilement, mais si vous chargez toutes les images dans une boucle, il a gagné ' t mettez à jour le visuel jusqu'à ce que vous ayez fini de charger toutes les images. L'interface utilisateur est sensible pendant ce temps, cependant, tout le chargement est sur un thread séparé.

Alternativement, si vous chargez toutes vos images dans une boucle, vous pouvez essayer un improved version of Windows Forms DoEvents method (faites défiler jusqu'à l'exemple). Vous appelez cela après avoir chargé chaque image et cela donnera à l'interface utilisateur une chance de se mettre à jour (interaction de l'utilisateur, etc.). C'est l'approche que j'ai utilisée lors du chargement des carreaux de carte pour mon projet et qui est plus facile que la première.

+1

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

Questions connexes