这是我的XAML:
NaN
这样我就可以将项目添加到ListView:
<ListView MouseDoubleClick="ImageList_MouseDoubleClick" Name="ImageList" Background="#353535" Grid.Row="2" Margin="0 5 0 0">
<ListView.ItemTemplate>
<DataTemplate>
<Grid Cursor="Hand" Width="200" Height="130" VerticalAlignment="Center" HorizontalAlignment="Left">
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="30"/>
</Grid.RowDefinitions>
<Image Source="{Binding ImgPath}" Grid.Row="0"/>
<Label FontSize="14" Foreground="White" Grid.Row="1" HorizontalAlignment="Center" Content="{Binding Name}"/>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Horizontal" Width="{Binding Path=ActualWidth, ElementName=ImageList}"/>
</ItemsPanelTemplate>
</ListView.ItemsPanel>
这段代码可以很好地处理一些图像,但是当我尝试打开一个包含100多张图片的文件夹时,我的程序崩溃了。我做错了什么或我能做些什么来优化我的程序?
答案 0 :(得分:1)
您可以使用视图模型异步加载缩略图图像文件,并通过设置npm eject
或DecodePixelWidth
属性来限制其大小。
DecodePixelHeight
你会绑定到这样的视图模型:
public class ImageData
{
public string Name { get; set; }
public ImageSource ImageSource { get; set; }
}
public class ViewModel
{
public ObservableCollection<ImageData> Images { get; }
= new ObservableCollection<ImageData>();
public async Task LoadFolder(string folderName, string extension = "*.jpg")
{
Images.Clear();
foreach (var path in Directory.EnumerateFiles(folderName, extension))
{
Images.Add(new ImageData
{
Name = Path.GetFileName(path),
ImageSource = await LoadImage(path)
});
}
}
public Task<BitmapImage> LoadImage(string path)
{
return Task.Run(() =>
{
var bitmap = new BitmapImage();
using (var stream = new FileStream(path, FileMode.Open, FileAccess.Read))
{
bitmap.BeginInit();
bitmap.DecodePixelHeight = 100;
bitmap.CacheOption = BitmapCacheOption.OnLoad;
bitmap.StreamSource = stream;
bitmap.EndInit();
bitmap.Freeze();
}
return bitmap;
});
}
}
并填充它,例如在某些异步输入事件处理程序中,如:
<Window.DataContext>
<local:ViewModel/>
</Window.DataContext>
...
<ListBox ItemsSource="{Binding Images}"
ScrollViewer.HorizontalScrollBarVisibility="Disabled">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<Grid Width="200" Height="130">
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="30"/>
</Grid.RowDefinitions>
<Image Source="{Binding ImageSource}"/>
<TextBlock Grid.Row="1" Text="{Binding Name}"/>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
答案 1 :(得分:0)
经过一段时间,我发现了这个问题的几个解决方案。对我来说,有一些简单的方法,以及一些更难的方法。 我认为最简单的方法是: 在我的问题代码中,我们需要更改以下代码:
<ItemsPanelTemplate>
<WrapPanel Orientation="Horizontal" Width="{Binding Path=ActualWidth, ElementName=ImageList}"/>
</ItemsPanelTemplate>
“WrapPanel”替换“VirtualizingStackPanel”。通过这种方式,程序将以用户@mkArtak建议的方式工作:
此外,在底部区域显示图像缩略图时,您应该使用某种虚拟化,因为您不想一次加载所有图像。感觉像很常见的场景,可以控制某个地方可用的控件,您可以重复使用。我们的想法是只加载每边可见+2的图像。然后,在用户滚动时加载其他任何内容。
据我所知,这是virtualization。当然,您可以调整虚拟化的方式。您可以在互联网上找到相关信息。
还有一个更难的方法:使用async \等待建议的用户@Clemens
您可以拥有一个以异步方式加载缩略图图像文件的视图模型,并通过设置DecodePixelWidth或DecodePixelHeight属性来限制其大小。
此外,我们可以使用这两种方式,我认为这将是最佳方式。
非常感谢大家帮忙找到解决这个问题的方法。