首页 > 解决方案 > WPF C#在堆栈面板中显示图像

问题描述

我实际上正在解决堆栈面板和我想在其中显示的图像的问题。

我的方法是:因为只有大约 50 张图片要显示,所以我只获取 ti 图像,从中制作缩略图,然后将其一张一张地放在我程序左侧的堆栈面板中。(作为位图)用户可以单击图像并使用图像执行操作。所需数量约为 50 张图像。

新状态:新状态是所需的图像数量约为 500 多 10 倍。问题是当我添加它时我的缩略图太小了:

列表中的 foreach 图像执行:

我在某处看到使用了一个图片框,不确定这是否对我有帮助。

我正在考虑创建图片链接列表(每个链接 50 个),例如首先放在滚动条中,当滚动条到达底部时,加载下一个,当顶部到达时加载上一个列表。

问题是我达到了最大进程内存约 175 张图像。我正在等待垃圾收集器在每个周期后完成它的工作。

也许我的方法不好或应该有所不同,所以这就是为什么我要问使用哪种方法来解决您建议的这个问题。

照片的来源只是大小为 150x150 的缩略图文件夹。

图像在一定的时间内一张一张地添加(每隔一秒左右一张照片)

谢谢

标签: wpfimageviewstackpanel

解决方案


一个实现的例子。

  1. 创建图像源的集合。
    该集合可以包含一个字符串或一个带有图像路径的 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; }
    }
}
  1. 将 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 的列表导致程序最慢。我已经做了测试。你能确认或反驳吗?

Тестирование。

  1. 超过 1200 张 JPG 和 PNG 格式的图像预先记录在“C:\150x150”文件夹中。

  2. 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;
        }
    }
  1. 在右上角的视图中显示了获取所有文件的路径所花费的时间。
    左侧是一个列表框,显示所有文件的大小为 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>
  1. 结果:获取路径的时间为12-14 ms,图像即时显示。
    滚动时根本没有滞后

  2. 对于从 128x128 到 4200x2800 的任意格式的图像文件也进行了验证。
    结果是一样的。


推荐阅读