WPF BitmapImage DownloadCompleted event never raised

时光总嘲笑我的痴心妄想 提交于 2019-12-12 04:39:31

问题


I have a WPF image control which its source property is bound to a property "ImageSrc" that returns an Image object.

<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>

Converter:

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();
    }
}

The problem I am suffering is that DownloadCompleted event for BitmapImage is never raised so line:

vm.Method();

is never executed and hence that Method() in my view model is never executed.

I have checked that the converter is executed correctly when I update Source property from Image object in view using the ImageSrc property bound in view model.

What am I doing wrong?


回答1:


I found a way to do this although not quite the best method but I struggled for about a whole day messing with binding triggers and available methods with images and streams. What I ended up doing was assigning a global boolean saying the image has been changed and then using the Image.LayoutUpdated action to check for that boolean. Once it sees the Boolean and verifies the image size is not zero, it inverts the boolean (so it doesn't run again) and does what needs to be done on Image loaded/in view.




回答2:


Take a look to the BitmapImage DownloadCompleted event documentation, Remarks section:

This event may not be raised for all types of bitmap content.




回答3:


The DownloadCompleted event isn't fired because no download is made when a BitmapImage is created from a stream.

You should not do this by a Binding Converter, but instead have another view model property of type ImageSource with an asynchronous Binding.

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;
   }
}

Then bind to this property like this:

<Image Source="{Binding ImageSource, IsAsync=True}"/>

Instead of a BitmapImage you may also create a BitmapFrame with a bit less code:

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;
    }
}


来源:https://stackoverflow.com/questions/46814636/wpf-bitmapimage-downloadcompleted-event-never-raised

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!