【问题标题】:Load lots of images in wpf在 wpf 中加载大量图像
【发布时间】:2015-07-22 23:19:45
【问题描述】:

我有大量图片需要加载到我的 wpf 应用程序中。我用 BackgroundWorker 尝试过,但它无法创建显示图像的切换按钮。

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

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

<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;
    }

【问题讨论】:

  • 没有看过你的任何代码就很难说。
  • @Clemens 添加了一些代码
  • @VitorM.Barbosa 这不是问题,它显示它们阻止了用户界面。
  • 您应该改用 ListBox,并将其 ItemsSource 属性绑定到图像文件路径的集合。在 ListBox 的 ItemTemplate 中,使用 Image 控件并将其 Source 属性绑定到文件路径,如&lt;Image Source="{Binding}"/&gt;。所有加载都将由 WPF BitmapFrame 类异步完成,ImageSourceConverter 在内部使用该类,该类自动将字符串转换为 ImageSource。这种方法还可以从虚拟化中受益,即 ListBox 项目在滚动到视图中之前不会被加载。

标签: c# wpf multithreading


【解决方案1】:

为所有图像创建一个列表框,为图像创建一个可观察的集合。我不会使用该图像,但会为该图像创建一个分辨率较低的缩略图。
图像的每个视图模型都将使用用于显示缩略图的视图模型的数据模板来显示。
还可以在这里快速查看图像的异步加载 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>

【讨论】:

    【解决方案2】:

    好的,我知道了。

    将 xaml 中的列表框与 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);
                }
            }
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-06-15
      • 1970-01-01
      • 1970-01-01
      • 2011-03-10
      • 2011-07-14
      • 2010-10-08
      • 2012-08-14
      相关资源
      最近更新 更多