ImageSourceConverter error for Source=null

20,917

Solution 1

@AresAvatar is right in suggesting you use a ValueConverter, but that implementation does not help the situation. This does:

public class NullImageConverter :IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value == null)
            return DependencyProperty.UnsetValue;
        return value;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        // According to https://msdn.microsoft.com/en-us/library/system.windows.data.ivalueconverter.convertback(v=vs.110).aspx#Anchor_1
        // (kudos Scott Chamberlain), if you do not support a conversion 
        // back you should return a Binding.DoNothing or a 
        // DependencyProperty.UnsetValue
        return Binding.DoNothing;
        // Original code:
        // throw new NotImplementedException();
    }
}

Returning DependencyProperty.UnsetValue also addresses the performance issues from throwing (and ignoring) all those exceptions. Returning a new BitmapSource(uri) would also get rid of the exceptions, but there is still a performance hit (and it isn't necessary).

Of course, you'll also need the plumbing:

In resources:

<local:NullImageConverter x:Key="nullImageConverter"/>

Your image:

<Image Source="{Binding Path=ImagePath, Converter={StaticResource nullImageConverter}}"/>

Solution 2

I used Pat's ValueConverter technique and it worked great. I also tried the TargetNullValue technique, by flobodob from here, and it also works great. It's easier and cleaner.

<Image Source="{Binding LogoPath, TargetNullValue={x:Null}}" />

TargetNullValue is simpler, and requires no converter.

Solution 3

Bind your image directly on an object and return "UnsetValue" if necessary

<Image x:Name="Logo" Source="{Binding ImagePath}"  />

The property in your ViewModel :

    private string _imagePath = string.Empty;
    public object ImagePath 
    {
        get
        {
            if (string.IsNullOrEmpty(_imagePath))
                return DependencyProperty.UnsetValue;

            return _imagePath;
        }
        set
        {
            if (!(value is string)) 
                return;

            _imagePath = value.ToString();
            OnPropertyChanged("ImagePath");
        }
    }
Share:
20,917
Kai G
Author by

Kai G

I'm a software engineer from Brisbane, Australia. I've previously spent a few years in the US working at AWS.

Updated on October 14, 2020

Comments

  • Kai G
    Kai G over 3 years

    I'm binding the Source property of an Image to a string. This string may be null in which case I just don't want to display an Image. However, I'm getting the following in my Debug output:

    System.Windows.Data Error: 23 : Cannot convert '<null>' from type '<null>' to type 'System.Windows.Media.ImageSource' for 'en-AU' culture with default conversions; consider using Converter property of Binding. NotSupportedException:'System.NotSupportedException: ImageSourceConverter cannot convert from (null). at System.ComponentModel.TypeConverter.GetConvertFromException(Object value) at System.Windows.Media.ImageSourceConverter.ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, Object value) at MS.Internal.Data.DefaultValueConverter.ConvertHelper(Object o, Type destinationType, DependencyObject targetElement, CultureInfo culture, Boolean isForward)'

    I'd prefer if this wasn't displayed as it's just noise - is there any way to suppress it?

  • Andrew Garrison
    Andrew Garrison over 12 years
    Amazing how much faster my code runs now when I consider a null value for an image source. Thanks for that, though I would recommend also handling the string.IsNullOrWhitespace case as well if 'value' is a string.
  • Unixcited
    Unixcited almost 12 years
    Is there a way to specify DependencyProperty.UnsetValue as the TargetNullValue in binding? It may eliminate the need for converter?
  • erodewald
    erodewald about 11 years
    I tested this with great success: TargetNullValue={x:Static DependencyProperty.UnsetValue} note: If it's an empty string, it will not work. One possible solution if you are doing something like building a string path in a getter, is to simply return null instead of string.Empty.
  • buckley
    buckley about 11 years
    This can be made even simpler by just returning the value in the Convert function. In effect this will simple pipe through the value unaltered but it will not show the binding error
  • Kai G
    Kai G almost 11 years
    While that probably works I think Pat's answer is better because you only have to define the converter once - with your solution you'd have to re-implement this for every Image property.
  • omini data
    omini data about 8 years
    i did as you had done but i i getting an error <Window.Resources> <local:NullImageConverter x:Key="nullImageConverter"/> The type 'local:NullImageConverter' was not found. Verify that you are not missing an assembly reference and that all referenced assemblies have been built.
  • Scott Chamberlain
    Scott Chamberlain about 8 years
    You are not supposed to throw a NotImplmentedException if you don't support a CovnertBack. Per the MSDN you should either return DependencyProperty.UnsetValue or Binding.DoNothing depending on if you want the binding to use the fallback value and default value or not.
  • pixel
    pixel over 7 years
    You are binding to a string, yet your property returns object?
  • Epirocks
    Epirocks almost 7 years
    omini data - you need to make sure you put the converter at the right namespace. local: will only work if that is where you put it.