wpf - WPF C#在堆栈面板中显示图像
问题描述
我实际上正在解决堆栈面板和我想在其中显示的图像的问题。
我的方法是:因为只有大约 50 张图片要显示,所以我只获取 ti 图像,从中制作缩略图,然后将其一张一张地放在我程序左侧的堆栈面板中。(作为位图)用户可以单击图像并使用图像执行操作。所需数量约为 50 张图像。
新状态:新状态是所需的图像数量约为 500 多 10 倍。问题是当我添加它时我的缩略图太小了:
列表中的 foreach 图像执行:
- 创建缩略图
- 将点击或触摸事件添加到该缩略图
- 将该缩略图添加到堆栈面板
我在某处看到使用了一个图片框,不确定这是否对我有帮助。
我正在考虑创建图片链接列表(每个链接 50 个),例如首先放在滚动条中,当滚动条到达底部时,加载下一个,当顶部到达时加载上一个列表。
问题是我达到了最大进程内存约 175 张图像。我正在等待垃圾收集器在每个周期后完成它的工作。
也许我的方法不好或应该有所不同,所以这就是为什么我要问使用哪种方法来解决您建议的这个问题。
照片的来源只是大小为 150x150 的缩略图文件夹。
图像在一定的时间内一张一张地添加(每隔一秒左右一张照片)
谢谢
解决方案
一个实现的例子。
- 创建图像源的集合。
该集合可以包含一个字符串或一个带有图像路径的 Url。在这种情况下,仅当图像显示在窗口中时才会创建图像。
您还可以设置 ImageSource 的实例(或者更确切地说是从它派生的类)。在这种情况下,图像将立即加载到内存中。
还设置用于指定所选图像的属性。
using System;
using System.Collections.ObjectModel;
using System.Windows.Media.Imaging;
namespace ImagesViewer
{
public class ImagesViewerViewModel
{
public ObservableCollection<object> ImagesSource { get; }
= new ObservableCollection<object>()
{
"https://miro.medium.com/max/2400/0*UEtwA2ask7vQYW06.png",
new Uri("https://149351115.v2.pressablecdn.com/wp-content/uploads/2021/06/stackoverflow-prosus-blue-orange.png"),
new BitmapImage(new Uri("https://amazinghiring.com/wp-content/uploads/2019/03/jpddcgb89ow.jpg"))
};
public object SelectedImage { get; set; }
}
}
- 将 ListBox 源绑定到创建的集合。
在元素模板中,指定与元素绑定的图像和所需的缩略图大小。
将所选项目分配给所选图像的属性。
ListBox 默认内置了一个 VirtualizingStackPanel,因此您无需采取任何额外的步骤来限制使用内存。
在查看区域中,将 Image 设置为绑定到所选图像的属性。
<Window x:Class="ImagesViewer.ImagesViewerWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:ImagesViewer"
mc:Ignorable="d"
Title="ImagesViewerWindow" Height="450" Width="800">
<FrameworkElement.DataContext>
<local:ImagesViewerViewModel/>
</FrameworkElement.DataContext>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<ListBox ItemsSource="{Binding ImagesSource}"
SelectedItem="{Binding SelectedImage}">
<ListBox.ItemTemplate>
<DataTemplate>
<Image Source="{Binding}" Margin="5"
Width="100" Height="100"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<Image Grid.Column="1"
Source="{Binding SelectedImage}"/>
</Grid>
</Window>
好的,但是正如我已经提到的,170 150x150 的列表导致程序最慢。我已经做了测试。你能确认或反驳吗?
Тестирование。
超过 1200 张 JPG 和 PNG 格式的图像预先记录在“C:\150x150”文件夹中。
ViewModel 获取此文件夹中的文件列表并创建一个字符串数组及其路径。此操作的时间也被记录下来。
public class ImagesViewModel
{
public IEnumerable<string> ImagesPaths { get; }
public long ExecutionTimeGetPaths {get;}
public ImagesViewModel()
{
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
ImagesPaths = Directory.GetFiles("C:/150x150")
.Where(path => path.EndsWith(".jpg") || path.EndsWith(".png"))
.ToArray();
stopwatch.Stop();
ExecutionTimeGetPaths = stopwatch.ElapsedMilliseconds;
}
}
- 在右上角的视图中显示了获取所有文件的路径所花费的时间。
左侧是一个列表框,显示所有文件的大小为 150x150 的图像。
<Window x:Class="Eee.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:Eee"
mc:Ignorable="d"
Title="MainWindow" Height="1000" Width="300">
<Window.DataContext>
<local:ImagesViewModel/>
</Window.DataContext>
<Grid>
<TextBlock Text="{Binding ExecutionTimeGetPaths}"
HorizontalAlignment="Right" VerticalAlignment="Top"
FontSize="30" Margin="10"/>
<ListBox ItemsSource="{Binding ImagesPaths}" HorizontalAlignment="Left">
<ListBox.ItemTemplate>
<DataTemplate>
<Image Source="{Binding}"
Width="150" Height="150"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</Window>
结果:获取路径的时间为12-14 ms,图像即时显示。
滚动时根本没有滞后。对于从 128x128 到 4200x2800 的任意格式的图像文件也进行了验证。
结果是一样的。
推荐阅读
- database - 使用 ETL 工具 (Datasatge 11.7) 或任何其他方法将数据从 Vertica 复制到 Redis
- material-table - 限制材料表 1.36.2 上的选择数量?
- django - 提示:也许您的意思是引用该列
- asp.net-core - 如何将我的 Web 项目 A 中的外部布局应用到我的 Web 项目 B(asp net core)中?
- javascript - 从 JavaScript 传递 PowerShell 参数值
- python - 将字典映射到数据框,字典值为列表
- gradle - Kotlin 上 Gradle 脚本中的命令行问题
- azure - 每 10 分钟从 azure webjob 或 azure 函数创建 PDF 或 excel
- javascript - 如何通过 graphQL 和 AWS AppSync 发送 JSON 数组以将数据添加到 Dynamo Table?
- c# - WPF DataGrid - 如何在行编辑时连续显示一个按钮(检测编辑模式)?