WPF BitmapImage DownloadCompleted 事件从未引发
Posted
技术标签:
【中文标题】WPF BitmapImage DownloadCompleted 事件从未引发【英文标题】:WPF BitmapImage DownloadCompleted event never raised 【发布时间】:2018-03-30 14:10:51 【问题描述】:我有一个 WPF 图像控件,它的源属性绑定到返回 Image 对象的属性“ImageSrc”。
<Window x:Class="My.Apps.WPF.Main"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:viewmodel="clr-namespace:My.Apps.WPF.ViewModels"
xmlns:classes="clr-namespace:My.Apps.WPF.Classes"
>
<Window.Resources>
<viewmodel:MyViewModel x:Key="myViewModel" />
<classes:ImgToSrcConverter x:Key="imgToSrcConverter" />
</Window.Resources>
<Grid x:Name="TopGrid" DataContext="StaticResource myViewModel">
<Image Grid.Row="0">
<Image.Source>
<MultiBinding NotifyOnTargetUpdated="True" Converter="StaticResource imgToSrcConverter">
<Binding Path="ImageSrc" />
<Binding Path="." />
</MultiBinding>
</Image.Source>
</Image>
</Grid>
</Window>
转换器:
public class ImgToSrcConverter : IMultiValueConverter
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
Image image = values[0] as Image;
if (image != null)
MemoryStream ms = new MemoryStream();
image.Save(ms, image.RawFormat);
ms.Seek(0, SeekOrigin.Begin);
BitmapImage bi = new BitmapImage();
bi.BeginInit();
bi.StreamSource = ms;
bi.EndInit();
ViewModel vm = values[1] as ViewModel;
bi.DownloadCompleted += (s, e) =>
vm.Method();
;
return bi;
return null;
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
throw new NotImplementedException();
我遇到的问题是 BitmapImage 的 DownloadCompleted 事件从未引发过这样一行:
vm.Method();
永远不会执行,因此我的视图模型中的 Method() 永远不会执行。
当我使用视图模型中绑定的 ImageSrc 属性从视图中的 Image 对象更新 Source 属性时,我检查了转换器是否正确执行。
我做错了什么?
【问题讨论】:
【参考方案1】:我找到了一种方法来做到这一点,虽然不是最好的方法,但我花了一整天的时间来处理绑定触发器和图像和流的可用方法。我最终做的是分配一个全局布尔值,表示图像已更改,然后使用 Image.LayoutUpdated 操作来检查该布尔值。一旦它看到布尔值并验证图像大小不为零,它就会反转布尔值(因此它不会再次运行)并在图像加载/视图中执行需要执行的操作。
【讨论】:
【参考方案2】:看看BitmapImage
DownloadCompleted
事件documentation,备注部分:
可能不会为所有类型的位图内容引发此事件。
【讨论】:
【参考方案3】:DownloadCompleted 事件未触发,因为从流创建 BitmapImage 时未进行下载。
您不应该通过绑定转换器来执行此操作,而应使用另一个带有异步绑定的 ImageSource 类型的视图模型属性。
private ImageSource imageSource;
public ImageSource ImageSource
get
if (imageSource == null)
using (var stream = new MemoryStream())
...
var bitmap = new BitmapImage();
bitmap.BeginInit();
bitmap.CacheOption = BitmapCacheOption.OnLoad;
bitmap.StreamSource = stream;
bitmap.EndInit();
bitmap.Freeze(); // necessary for async binding
imageSource = bitmap;
Method();
return imageSource;
然后像这样绑定到这个属性:
<Image Source="Binding ImageSource, IsAsync=True"/>
你也可以用更少的代码创建一个 BitmapFrame,而不是 BitmapImage:
private ImageSource imageSource;
public ImageSource ImageSource
get
if (imageSource == null)
using (var stream = new MemoryStream())
...
imageSource = BitmapFrame.Create(
stream, BitmapCreateOptions.None, BitmapCacheOption.OnLoad);
Method();
return imageSource;
【讨论】:
好的,但是您的解决方案确保我只有在图像被渲染、准备好并且对用户可见/显示时才执行 Method()?我需要一种方法来仅在图像对用户可见之后才执行方法,而不是之前。通过在 ImageSource 属性中调用 Method,我不确定是否仅在用户可见图像后才调用它。可能会发生 Method() 在图像显示并对用户可见之前几秒钟执行的情况。 查看编辑后的答案,了解如何只调用一次 Method()。当渲染线程最终在屏幕上显示图像时,Afaik 无法获得通知。这是你能得到的最好的。【参考方案4】:DownloadCompleted 事件没有被触发,我遇到了类似的问题。 在我用类中的 BitmapImage 属性替换方法中的局部变量之后。 事件再次被触发。 应该是垃圾收集器,收集了参考资料。
【讨论】:
以上是关于WPF BitmapImage DownloadCompleted 事件从未引发的主要内容,如果未能解决你的问题,请参考以下文章
WPF BitmapImage DownloadCompleted 事件从未引发
从 System.Drawing.Bitmap 加载 WPF BitmapImage
WPF BitmapImage 占用资源无法释放无法删除问题