在wpf中加载大量图像

时间:2015-07-21 16:44:33

标签: c# wpf multithreading

我需要在我的wpf应用中加载大量图片。我尝试使用BackgroundWorker但它无法创建显示图像的togglebutton。

是否有更好的方法来加载大量图像?它们需要是可选择的,因为用户可以选择图像。

到目前为止,这是我的一些代码:

<WrapPanel Name="mFolderImages">
    <ToggleButton Width="150" Margin="5" Style="{StaticResource ImageList}">
         <ToggleButton.Content>
              <Image Source="/Managment;component/images/example.png" />
         </ToggleButton.Content>
    </ToggleButton>
</WrapPanel>

private void GetFolderImagesThreadFinished(object sender, RunWorkerCompletedEventArgs e) {
        if (e.Result != null && e.Result is List<BitmapImage>) {
            List<BitmapImage> images = (List<BitmapImage>)e.Result;
            foreach (var image in images) {
                Image img = new Image();
                img.Source = image;
                img.Margin = new Thickness(5);

                ToggleButton btn = new ToggleButton();
                btn.Content = img;
                btn.Width = 150;
                btn.Margin = new Thickness(5);
                btn.IsEnabled = true;
                btn.Click += ChangeSelectedImage;
                btn.Style = this.FindResource("ImageList") as Style;
                mFolderImages.Children.Add(btn);
            }
        }
        mProgress.Visibility = Visibility.Collapsed;
        mFolderImages.IsEnabled = true;
    }

    private void GetFolderImagesThread(object sender, DoWorkEventArgs e) {
        string imagePath = Config.GetValue("ImagePath");
        if (!Directory.Exists(imagePath)) return;

        string[] files = Directory.GetFiles(imagePath);
        int progress = 0;
        List<BitmapImage> images = new List<BitmapImage>();

        foreach(var file in files) {
            if (file.EndsWith(".jpg") || file.EndsWith(".png")) {
                try {
                    BitmapImage bmp = new BitmapImage();
                    bmp.BeginInit();
                    bmp.UriSource = new Uri(file, UriKind.Absolute);
                    bmp.EndInit();
                    bmp.Freeze();
                    images.Add(bmp);
                } catch (Exception ex) {
                    Console.Write(ex.Message);
                }
            }
            ++progress;
            mThread.ReportProgress((int)((progress / (float)files.Length) * 100));
        }
        e.Result = images;
    }

2 个答案:

答案 0 :(得分:1)

为所有图像创建一个列表框,为图像创建一个可观察的集合。我不会使用图像,但会为图像创建分辨率较低的缩略图 将使用视图模型的datatemplate显示图像的每个viewModel,该模型将显示缩略图 还可以快速查看图像的异步加载 Loading Images asynchronous in C#

<ListBox ItemsSource="{Binding ImagesCollection}" 
   SelectedIndex="0">
  <ListBox.ItemTemplate>
    <DataTemplate>
      <Image Source="{Binding}"/> <!--bind to the field of the tumbnail using a converter if needed
    </DataTemplate>
  </ListBox.ItemTemplate>
</ListBox>

答案 1 :(得分:0)

好的,我明白了。

使用xaml中的Listbox与ItemsPanel中的Wrappanel和ItemTemplate中的图像。

然后在代码中我使用BackgroundWorker加载图像并调整其大小,并使用reportProgress将其添加到集合中。

<ListBox ItemsSource="{Binding Path=ImagesCollection, IsAsync=True}" SelectedIndex="0" ScrollViewer.HorizontalScrollBarVisibility="Disabled">
   <ListBox.ItemsPanel>
      <ItemsPanelTemplate>
           <WrapPanel IsItemsHost="True" />
      </ItemsPanelTemplate>
   </ListBox.ItemsPanel>
   <ListBox.ItemTemplate>
       <DataTemplate>
          <Image Width="150" Height="150"  Source="{Binding}" />
       </DataTemplate>
   </ListBox.ItemTemplate>
</ListBox>

private void LoadImageProgress(object sender, ProgressChangedEventArgs e) {
        if (e.UserState != null && e.UserState is BitmapImage) {
            ImagesCollection.Add((BitmapImage)e.UserState);
        }
    }

    private void LoadImageThread(object sender, DoWorkEventArgs e) {
        string imagePath = Config.GetValue("ImagePath");
        if (!Directory.Exists(imagePath)) return;

        string[] files = Directory.GetFiles(imagePath);
        foreach (var file in files) {
            if (file.EndsWith(".jpg") || file.EndsWith(".png")) {
                var img = new Bitmap(file);
                float scale = Math.Min(150 / (float)img.Width, 150 / (float)img.Height);

                var bmp = new Bitmap(150, 150);
                var graph = Graphics.FromImage(bmp);

                var scaleWidth = (int)(img.Width * scale);
                var scaleHeight = (int)(img.Height * scale);

                graph.DrawImage(img, new System.Drawing.Rectangle((150 - scaleWidth) / 2, (150 - scaleHeight) / 2, scaleWidth, scaleHeight));

                BitmapImage retImg = new BitmapImage();
                using (MemoryStream mem = new MemoryStream()) {
                    bmp.Save(mem, System.Drawing.Imaging.ImageFormat.Bmp);
                    mem.Position = 0;
                    retImg.BeginInit();
                    retImg.StreamSource = mem;
                    retImg.CacheOption = BitmapCacheOption.OnLoad;
                    retImg.EndInit();
                    retImg.Freeze();
                }
                mThread.ReportProgress(0, retImg);

                if (mThread.CancellationPending) return;
                //Thread.Sleep(1000);
            }
        }
    }