在wpf中加载大量图像
本文关键字:图像 加载 wpf | 更新日期: 2023-09-27 18:03: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;
}
为所有图像创建一个列表框,为图像创建一个可观察的集合。我不会使用图像,但会为图像创建一个分辨率较低的缩略图。
图像的每个viewModel将使用视图模型的数据模板来显示,该数据模板将显示缩略图。
还可以在这里快速查看图像的异步加载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>
好的,我知道了。
使用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);
}
}
}