WPF BitmapImage从未提出过DownloadCompleted事件

时间:2017-10-18 16:10:16

标签: c# wpf mvvm visual-studio-2008 .net-3.5

我有一个WPF图像控件,其源属性绑定到一个属性" ImageSrc"返回一个Image对象。

<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属性时检查了转换器是否正确执行。

我做错了什么?

4 个答案:

答案 0 :(得分:1)

我找到了一种方法来做到这一点虽然不是最好的方法,但我一整天都在努力解决绑定触发器和图像和流的可用方法。我最终做的是分配一个全局布尔值,说明图像已被更改,然后使用Image.LayoutUpdated操作来检查该布尔值。一旦它看到布尔值并验证图像大小不为零,它就会反转布尔值(因此它不会再次运行)并执行需要在图像加载/视图中完成的操作。

答案 1 :(得分:0)

查看BitmapImage DownloadCompleted活动documentation备注部分:

  

可能不会针对所有类型的位图内容引发此事件。

答案 2 :(得分:0)

由于在从流中创建BitmapImage时未进行下载,因此未触发DownloadCompleted事件。

您不应该通过绑定转换器执行此操作,而是使用另一个具有异步绑定的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;
    }
}

答案 3 :(得分:0)

DownloadCompleted 事件没有被触发,我遇到了类似的问题。 在我用类中的 BitmapImage 属性替换了方法中的局部变量之后。 事件再次被触发。 可能是垃圾收集器,收集了参考。