【C#】ListBox中找到多个image中的其中一个并重置赋值以便清理占用内存

1.ListBox中定义多个image

定义ListBox前台代码及Image控件的赋值

cs 复制代码
<ListBox Background="{DynamicResource BackgroundBrush}" 
     ItemsSource="{Binding ElementName=DRFinish,Path=Images}" 
     Style="{x:Null}" Name="ImageList"
     ItemContainerStyle="{StaticResource imageItemStyle}">
<ListBox.ItemsPanel>
    <ItemsPanelTemplate>
        <WrapPanel></WrapPanel>
    </ItemsPanelTemplate>                                    
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
    <DataTemplate>
        <Border Width="100" Height="170" Tag="{Binding}" MouseDown="imageListItemBorder_MouseDown"  Name="imageListItemBorder">
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition Height="20"/>
                    <RowDefinition Height="90"/>
                    <RowDefinition Height="20"/>
                </Grid.RowDefinitions>
                <Image Grid.Row="0" Visibility="{Binding Infor.ImageD,Converter={StaticResource boolVisibilityConverter}}" Name="ImageDelete" Source="../Resource/DeleteImage1.png" HorizontalAlignment="Left" VerticalAlignment="Top" Width="20" Height="20" />
                <Image Grid.Row="1" Source="{Binding ImageFullPath, Converter={StaticResource jpgConverter}}" Width="90" Height="90" />
                <Image Grid.Row="1" Visibility="{Binding Infor.DFilmed,Converter={StaticResource boolVisibilityConverter}}" Source="../Resource/DFilmed.png" HorizontalAlignment="Right" VerticalAlignment="Top" Width="20" Height="20"/>
            </Grid>
        </Border>
        <DataTemplate.Triggers>
            <DataTrigger Binding="{Binding Infor.ImageD}" Value="false">
                <Setter TargetName="ImageDelete" Property="Visibility" Value="Collapsed"/>
            </DataTrigger>
            <DataTrigger Binding="{Binding Infor.ImageD}" Value="true">
                <Setter TargetName="ImageDelete" Property="Visibility" Value="Visible" />
            </DataTrigger>
        </DataTemplate.Triggers>
    </DataTemplate>
</ListBox.ItemTemplate>
</ListBox>

2.后台操作

2.1使用方法

假设你有一个ListBox,并且你想要根据Name属性查找一个特定的Image控件:

设置 Source 属性为 null

cs 复制代码
try
{
    var image = FindImageByName("ImageDelete");
    if (image != null)
    {
      // 找到了Image,可以在这里做进一步的操作
      Console.WriteLine("找到了Image: " + image.Source);
    }
    else
    {
      Console.WriteLine("没有找到匹配的Image控件");
    }
}
catch (Exception ee) { }

Images.Clear();
ImageList.ItemsSource = null;

强制垃圾回收

cs 复制代码
// 强制垃圾回收
GC.Collect();
GC.WaitForPendingFinalizers();

使用 MemoryStream 加载图片

如果你是从字节流加载图片,使用完MemoryStream后应确保调用其Dispose方法,以释放与之相关的资源。

cs 复制代码
using (var stream = new MemoryStream(imageBytes))
{
    var bitmap = new BitmapImage();
    bitmap.BeginInit();
    bitmap.StreamSource = stream;
    bitmap.CacheOption = BitmapCacheOption.OnLoad; // 确保加载后释放流
    bitmap.EndInit();
    bitmap.Freeze(); // 使位图不可变,有助于提高性能和降低内存使用

    // 清除之前的图像
    image.Source = null;

    // 赋予新的图像
    image.Source = bitmap;
}

使用 BitmapCacheBitmapImageCacheOption 属性

当使用BitmapImage加载图片时,可以通过设置CacheOption属性来控制缓存行为。例如,使用OnLoad选项可以在图片加载到内存后立即释放文件流,从而减少内存占用。

cs 复制代码
var bitmap = new BitmapImage();
bitmap.BeginInit();
bitmap.CacheOption = BitmapCacheOption.OnLoad;
bitmap.UriSource = new Uri("path_to_your_image.jpg", UriKind.RelativeOrAbsolute);
bitmap.EndInit();

// 清除之前的图像
image.Source = null;

// 赋予新的图像
image.Source = bitmap;

2.2根据Name属性查找特定的Image控件

寻找其中一个Image控件的方法,根据Name属性查找特定的Image控件:

定义查找方法

cs 复制代码
private void FindImageByName(string name)
{
    foreach (var item in ImageList.Items)
    {
        // 获取 ListBoxItem 容器
        var listBoxItem = (ListBoxItem)ImageList.ItemContainerGenerator.ContainerFromItem(item);
        if (listBoxItem != null)
        {
            // 在 ListBoxItem 中查找 Image 控件
            var image = FindChild<System.Windows.Controls.Image>(listBoxItem, name);
            BitmapImage bitmapImage = image.Source as BitmapImage;
            if (bitmapImage != null)
            {
                if (bitmapImage.StreamSource != null)
                {
                    bitmapImage.StreamSource.Dispose();
                }
            }
        }
    }
}

辅助方法 FindChild

这个方法用于递归查找子控件:

cs 复制代码
public static T FindChild<T>(DependencyObject parent, string childName) where T : DependencyObject
{
    if (parent == null) return null;
    T foundChild = null;
    int childrenCount = VisualTreeHelper.GetChildrenCount(parent);
    for (int i = 0; i < childrenCount; i++)
    {
        var child = VisualTreeHelper.GetChild(parent, i);
        // 如果找到了匹配的子控件
        var childType = child as T;
        if (childType != null && !string.IsNullOrEmpty(childName))
        {
            var frameworkElement = child as FrameworkElement;
            if (frameworkElement != null && frameworkElement.Name == childName)
            {
                foundChild = (T)child;
                break;
            }
        }
        else if (childType != null)
        {
            foundChild = (T)child;
            break;
        }
        // 如果没有找到,递归查找子控件
        if (foundChild == null)
        {
            foundChild = FindChild<T>(child, childName);
        }
    }
    return foundChild;
}

在C#中,FindChild<T> 方法是一个泛型方法,用于在WPF(Windows Presentation Foundation)应用程序中查找特定类型的子元素。该方法定义如下:

  • T :这是一个类型参数,代表你希望找到的子元素的具体类型。例如,如果想要找一个 Button 类型的子元素,那么调用这个方法时,T 就是 Button

  • DependencyObject:这是所有WPF UI元素的基类,它提供了依赖属性系统,允许属性值的继承、资源引用等功能。

  • parent :这是开始搜索的起点对象,通常是一个包含其他UI元素的容器,比如 WindowGrid

  • childName :这是一个字符串参数,表示要找的子元素的名字。在XAML中,每个元素都可以有一个 x:Name 属性来标识它,这个参数就是用来匹配那个名字的。

  • where T : DependencyObject :这是一条约束,表明类型参数 T 必须是 DependencyObject 类或其派生类的实例。这是因为WPF中的UI元素都直接或间接地继承自 DependencyObject

这个方法的目的是递归地遍历给定父级元素的所有子元素,直到找到名称与 childName 匹配且类型为 T 的子元素为止。如果找到了这样的子元素,则返回该子元素;如果没有找到,则可能返回 null 或者某种形式的默认值,具体取决于方法的实现。

注意事项

确保 Name 属性已设置:在XAML中,确保你为每个Image控件设置了Name属性。

视觉树的复杂性:如果视觉树非常复杂,可能需要调整递归查找逻辑以确保能够正确找到目标控件。

性能考虑:如果ListBox中有大量项,频繁调用此方法可能会影响性能。在这种情况下,可以考虑缓存结果或优化查找逻辑。

相关推荐
Rose 使者40 分钟前
全国天气预报查询接口如何用C#进行调用?
c#·api·天气预报
夕泠爱吃糖1 小时前
Linux 文件内容的查询与统计
android·linux·c#
小码编匠1 小时前
WinForm 工业自动化上位机通用框架:注册登录及主界面切换实现
后端·c#·.net
码小跳1 小时前
Halcon案例(三):C#联合Halcon识别排线
计算机视觉·c#·halcon
l1o3v1e4ding2 小时前
python-docx 库教程
开发语言·python·c#
m0_516484673 小时前
C#winform多选框代码
开发语言·c#
I'mSQL3 小时前
Visual Studio 2022打包程序流程
ide·c#·自动化·.net·visual studio
一线码农3 小时前
MinHook 对.NET底层的 SendMessage 拦截真实案例反思
c#·.net·windbg
MasterNeverDown3 小时前
.NET 异步编程的核心优势
c#·async·wait