15

In XAML I have the following line:

<Image x:Name="MainImage" 
       Source="{x:Bind ViewModel.MainPic,Mode=OneWay,TargetNullValue={x:Null}}"
       Stretch="UniformToFill"/>

In ViewModel:

public string MainPic
{
    get
    {
        if (Data == null)
            return default(string);
        else
            return Data.Photos.ElementAtOrDefault(0).url;
    }
}

App compiles fine but during execution (since Data is populated after few seconds), the app crashes with the following exception:

System.ArgumentException: The parameter is incorrect.

Debugger breaks at:

            private void Update_ViewModel_MainPic(global::System.String obj, int phase)
            {
                if((phase & ((1 << 0) | NOT_PHASED | DATA_CHANGED)) != 0)
                {
 /*HERE>>*/          XamlBindingSetters.Set_Windows_UI_Xaml_Controls_Image_Source(this.obj23, (global::Windows.UI.Xaml.Media.ImageSource) global::Windows.UI.Xaml.Markup.XamlBindingHelper.ConvertValue(typeof(global::Windows.UI.Xaml.Media.ImageSource), obj), null);
                }
            }

Apparently, this occurs since MainPic is returning null.

Now, this code works fine in WP8.1. I have tried returning uri which results in Compile time error. I believe only string can be binded to image source in Win 10 (?) I just want a blank white area until data is populated hence I don't wish to give a local image source as fallback. Can someone help me port this for Win 10?


UPDATE:

Thanks to the users who answered, following conclusion is drawn (for UWP):

  • If you're binding image source to a string, it cannot be null or empty "". A singe character "x" or a space " " would work.
  • If you bind to a BitmapImage, returning null works.
  • You can use any of the methods mentioned by @Justin-xl . For me, changing all vm's to stop returning null was hard. So adding a simple convertor to xaml also does the trick.

Here's the converter code:

public object Convert(object value, Type targetType, object parameter, string language)
{
    if (string.IsNullOrEmpty(value as string))
    {
        return null;
    }
    else return new BitmapImage(new Uri(value as string, UriKind.Absolute));
}
Saurabh3321
  • 566
  • 3
  • 14

1 Answers1

15

If you use x:Bind, the Source of the Image needs to bind to a property of the exact same type ImageSource (e.g. BitmapImage) instead of string, otherwise it will throw a compile-time error, which is exactly a compile-time binding is supposed to do. The old binding allows strings 'cause it uses Reflection to resolve the type for you during run-time.

Turns out my explicit type theory was wrong (thanks to @igrali for pointing it out). The Source does take a string as long it's is not null or ''. So it leaves us two options to fix this.

Option 1

Keep your uri as a string, but do a check in your vm, once it's null or '', return some dummy text (even returning an a letter x would work!).

Option 2

Change the uri from a string to a BitmapImage. Then you can use TargetNullValue and FallbackValue to handle nulls and invalid bindings.

... FallbackValue='http://Assets/SplashScreen.png' TargetNullValue='http://Assets/SplashScreen.png'}"
Justin XL
  • 38,763
  • 7
  • 88
  • 133
  • 1
    Even though in this particular case the null string is causing problems, technically, using {x:Bind } to bind to strings with valid image Uris will still work. – Igor Ralic Aug 09 '15 at 01:31
  • @igrali you know what, I just tested it n your right! Interesting though it needs to a **valid** url otherwise it will throw a compile-time error. I will update the answer. – Justin XL Aug 09 '15 at 01:51
  • 1
    @igrali, looks like it doesn't even need a valid uri, as long as it's not empty, it won't throw compile-time errors! – Justin XL Aug 09 '15 at 02:21
  • 1
    Thanks both options worked. I wonder why they have changed the default converter that kicks in when a string is binded. It does not seem to handle null or empty string. Hence even a single space " " works – Saurabh3321 Aug 09 '15 at 05:48
  • Not exactly sure but it could be a bug in their conversion code? – Justin XL Aug 09 '15 at 05:50
  • 1
    Yes it looks like. I wonder why no-one has pointed out this. I have put a conclusion above along with a manual converter option to solve this issue. Changing code everywhere in vm was tedious for me since I use lot of null bindings. – Saurabh3321 Aug 09 '15 at 06:05
  • 1
    Thanks @JustinXL, you saved my day! – Sapan Ghafuri Aug 02 '16 at 19:44