WPF - 将许多图像逐个加载到ObservableCollection中

时间:2014-08-01 15:06:40

标签: wpf image backgroundworker observablecollection dispatcher

在WPF中,我试图将很多(数千)图像加载到ListBox WrapPanel中。

我尝试加载类似于Windows资源管理器窗口的图像。

到目前为止,我的代码加载了所有图片'名称,位置(作为标记)和占位符图像以加快加载时间:

Dim ofd As New Microsoft.Win32.OpenFileDialog()
ofd.Multiselect = True
ofd.Filter = "JPEG|*.jpg"

If ofd.ShowDialog() Then
   For Each f In ofd.FileNames
      Items.Add(New With {.img = New BitmapImage(New Uri("pack://application:,,,/Resources/PlaceholderPhoto.png")), .nam = Path.GetFileNameWithoutExtension(f), .tag = f})
   Next

  'The name of my ObservableCollection is Items'
  lstboxPhotos.ItemsSource = Items 
End If

那部分没问题。我想要做的是加载图像'动态缩略图(逐个)。我这样做是为了让用户可以在缩略图加载时与之交互并查看可用的图像数量。我尝试了几个不同的东西 - 后台工作人员,调度员和单独的线程。

我用来加载图片的代码如下:

    'i came from me doing a for..next for each image in Items collection'
    Dim bmp As New BitmapImage()
    bmp.BeginInit()
    bmp.DecodePixelWidth = 90
    bmp.DecodePixelHeight = 60
    bmp.CacheOption = BitmapCacheOption.OnLoad
    bmp.UriSource = New Uri(Items.Item(i).tag, UriKind.Absolute)
    bmp.EndInit()

    Items.Item(i).img = bmp

我在互联网上搜索。老实说,我不确定采取什么方向来做我需要做的事。

如果我需要澄清其他任何内容,请告诉我。先感谢您! :)

修改 好的,所以引用this article,使用第二个答案,我得到的项目一次加载一个。它加载所有项目'名字很好,但似乎在大约40个项目后停止加载图像。

如果有人能说明为什么它可能会停止加载缩略图,但继续加载项目'这些名字将是一个很大的帮助!谢谢!

2 个答案:

答案 0 :(得分:4)

使用将TypeConverter文件路径转换为string个对象的内置ImageSource,您可以快速轻松地完成此操作。举一个简单的例子,它将显示Pictures文件夹中所有图像的缩略图:

public ObservableCollection<string> FilePaths { get; set; }

...

FilePaths = new ObservableCollection<string>(Directory.GetFiles(
    Environment.GetFolderPath(Environment.SpecialFolder.MyPictures)));

...

<ItemsControl ItemsSource="{Binding FilePaths}">
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <Image Source="{Binding}" Width="100" Stretch="Uniform" />
        </DataTemplate>
    </ItemsControl.ItemTemplate>
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <WrapPanel />
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
</ItemsControl>

在此示例中,每个Image.Source属性都是直接与FilePaths集合中的一个文件路径绑定的数据。

答案 1 :(得分:1)

好的,我知道它已经有一段时间了,但我想发布我最终做的事情。

首先,我通常使用带有临时图像的ObservableCollection将所有图像名称加载到ListBox中:

Dim Items As New ObservableCollection(Of Object)
Dim Files() As String
...

For Each f In Files
    Items.Add(New With {.img = New BitmapImage(New Uri("/Resources/Photo.png")), .name = f})
Next

lbPhotos.ItemsSource = Items

然后我使用BackgroundWorker将每个占位符图像替换为实际图像:

Private WithEvents bw As New BackgroundWorker
Private Sub bw_DoWork(ByVal sender As Object, ByVal e As DoWorkEventArgs) Handles bw.DoWork
    ...

    For i = 0 To Items.Count - 1
        If bw.CancellationPending Then
            e.Cancel = True
        Else
            Dim n As String = Items(i).name
            Dim t As String = Items(i).tag

            Dim bmp As New BitmapImage
            bmp.BeginInit()                
            bmp.UriSource = New Uri(PathToImage, UriKind.Absolute)
            bmp.EndInit()
            bmp.Freeze()

            Dispatcher.BeginInvoke(Sub()
                                       Items.RemoveAt(i)
                                       Items.Insert(i, New With {.img = bmp, .name = n})
                                   End Sub)
        End If
    Next
End Sub

这允许用户在加载图像时与UI进行交互。