在 Windows 10 中处置图像控件
Posted
技术标签:
【中文标题】在 Windows 10 中处置图像控件【英文标题】:Dispose Image Control in Windows 10 【发布时间】:2015-12-21 09:09:00 【问题描述】:注意:通用 Windows 平台(又名 Windows 10 应用,不是 WPF)
我有大约 80 个图像文件需要显示在页面内的列表视图中。当用户返回上一页时,我需要处理图像控件,以便删除这些图像。
问题是直接绑定image uri 锁定图片文件,返回时没有释放
我正在使用 MVVMLight
一些代码:
public class FileNameToFullUriConverter : IValueConverter
public object Convert(object value, Type targetType, object parameter, string language)
string ori = value.ToString();
string file = ori.Split('/').Last();
string img = file.Split('.')[0] + ".png";
img = "ms-appdata:///local/" + StaticClass.ImageFolder + "/" + img;
return img;
public object ConvertBack(object value, Type targetType, object parameter, string language)
return null;
和 XAML
<DataTemplate>
<Grid>
<Image x:Name="Image2"
Grid.Column="1"
HorizontalAlignment="Left"
Source="Binding Page2.Page.file,
Converter=StaticResource FileNameToFullUriConverter,
Mode=OneWay"
Stretch="UniformToFill" />
</Grid>
</DataTemplate>
我试过了:
将列表设为空
清除列表(通过调用 ListViewName.Clear())
ViewModelLocator 中的调用清理
什么有效,但不能应用: 在 ViewModel 中,我添加了另一个类型为
的属性ObservableCollection<BitmapImage>
,然后将 ListView 绑定到此集合。 通过这种方式,所有的图像都会被加载到 RAM 中,不会锁定文件,但它会导致一个严重的问题:消耗过多的 RAM。通过直接绑定到 BitmapImage,我的应用程序使用 URI 绑定占用了大约 100 MB RAM 到 900 MB RAM。此外,加载到页面所需的时间会更长,因为它必须在列表完成呈现之前读取所有图像文件并将其加载到 RAM 中。
那么,如何在 Windows 10 中配置 Image Control?
PS:本图对照:Image Class in MSDN
【问题讨论】:
您能否尝试在不锁定文件本身的情况下以 StorageFile-s 的形式打开这些图像,然后在您的解决方案中使用它们而不是 BitmapImage? 【参考方案1】:您可以在页面后面的代码中维护您的图像控件列表。当应用程序返回时,您可以将每个图像的 Source 属性设置为 null :
<DataTemplate>
<Grid>
<Image Loaded="Image_Loaded" />
</Grid>
</DataTemplate>
在后面的代码中:
private List<Image> _images = new List<Image>();
private void Image_Loaded(object sender, RoutedEventArgs e)
_images.Add(sender as Image);
protected override void OnNavigatedFrom(NavigationEventArgs e)
base.OnNavigatedFrom(e);
foreach(var img in _images)
img.Source = null;
所有的锁都会被释放。
【讨论】:
对不起,这是我试过的。它的工作,但导致内存泄漏。应用程序从使用 100 MB RAM 上升到 900 MB RAM。 我正在考虑制作一个自定义图像控件,并将图像放置在该控件中,而不是使用默认控件【参考方案2】:我对图像控件不是很熟悉。在我看来,必须先处置位图图像,然后才能删除文件。问题是 bitmapImage 没有 Dispose 功能。
我在这里看到其他人在堆栈溢出中询问如何主动处置图像。我想你也必须这样做。
见: How to dispose bitmapsource
Delete a bitmapsource file
【讨论】:
谢谢,但这些解决方案适用于不同的平台。在 UWP 中,BitmapImage 没有 BeginInit 或 CacheOption.OnLoad 我在我的应用程序中遇到了同样的情况。 @Tuấn Trần 你的问题终于解决了吗? 抱歉,我最终使用了一张较小的图片(缩略图)。必须手动创建缩略图【参考方案3】:我遇到了同样的问题。我使用了一种解决方法,我不确定这是否是最好的方法。我添加了一个方法来删除已删除的项目,并在每次应用程序启动或列表刷新时调用该方法。
private ObservableCollection<BitmapImage> _items; // your collection which is bound to ListView
// deleting images of removed items
private async Task DeleteUnusedImages()
try
var folder = await ApplicationData.Current.LocalFolder.GetFolderAsync("folderName");
var files = await folder.GetFilesAsync(); // getting all files inside that folder
foreach (var file in files)
// checking if the image still exist in the collection or got removed
// if removed then remove it from the local folder too.
if (!_items.Any(i => i.ImageName.Contains(file.Name)))
await file.DeleteAsync(StorageDeleteOption.PermanentDelete);
catch (Exception ex)
问题是当您从绑定到 ListView 的集合中删除一个项目时,ListView 直到几次刷新才会释放该项目。删除项目后,我尝试通过转到应用程序的“LocalState”文件夹手动删除它,但它说它已被应用程序使用并且无法删除。
【讨论】:
以上是关于在 Windows 10 中处置图像控件的主要内容,如果未能解决你的问题,请参考以下文章
背水一战 Windows 10 (27) - 控件(文本类): TextBlock