x:Bind Converter and FallbackValue not collaborating (UWP 10)

MB.

I have a problem that involves a bunch of code, but I've isolated it down. If you want a TL;DR; jump to it further down. If you want a bit of context, here's my situation:

I have created three data converters for my bindings. One of them is a "string prefixer": it prefixes whatever you put in with a fixed string. In the current example, that fixed string is "ms-appx:///cache/". The second one turns a string type into an ImageSource, and the third one chains multiple converters together.

I've then created a Xaml resource which is called LocalCacheFile. Everything works as you would think. Xaml code for this looks like so:

<Image Source="{x:Bind imageSource,Converter={StaticResource LocalCacheFile}}" />

However, I'm having the following problem. If I try to use the FallbackValue to put a placeholder image for when imageSource is empty, I get weird behaviour in x:Bind only.

The following code works as one would expect:

<Image Source="{Binding imageSource,FallbackValue='ms-appx:///Assets/default.png',Converter={StaticResource LocalCacheFile}}" />

But

<Image Source="{x:Bind imageSource,FallbackValue='ms-appx:///Assets/default.png',Converter={StaticResource LocalCacheFile}}" />

does not!

I've isolated it down to just one converter and it is DependencyProperty.UnsetValue that x:Bind seems not to be handling.

TL;DR; Here is the code for my string prefixer, which if I use alone as a test triggers the same faulty behaviour:

public class StringPrefix : IValueConverter
{
    public string prefix { get; set; }

    public object Convert(object value, Type typeName, object parameter, string language)
    {
        if (value == DependencyProperty.UnsetValue || value == null || (string)value == "")
            return DependencyProperty.UnsetValue ;

        return (prefix + value.ToString());
    }

    public object ConvertBack(object value, Type typeName, object parameter, string language)
    {
        throw new NotImplementedException();
    }
}

The above converter works as you would expect it to (i.e. if the input string is empty, the fallback value is properly used) when using Binding. It raises a type exception when used with x:Bind.

What's up with this?


Edit: details about the exception.

This is the generated code:

        private void Update_project_imageSource(global::System.String obj, int phase)
        {
            if((phase & ((1 << 0) | NOT_PHASED | DATA_CHANGED)) != 0)
            {
                XamlBindingSetters.Set_Windows_UI_Xaml_Controls_Image_Source(this.obj16, (global::Windows.UI.Xaml.Media.ImageSource)this.LookupConverter("LocalCacheFile").Convert(obj, typeof(global::Windows.UI.Xaml.Media.ImageSource), null, null), null);
            }
        }

Exception details:

System.InvalidCastException was unhandled by user code
  HResult=-2147467262
  Message=Unable to cast object of type 'System.__ComObject' to type 'Windows.UI.Xaml.Media.ImageSource'.
  Source=Test
  StackTrace:
       at Test.Pages.ProjectView.ProjectView_obj1_Bindings.Update_project_imageSource(String obj, Int32 phase)
       at Test.Pages.ProjectView.ProjectView_obj1_Bindings.Update_project(Project obj, Int32 phase)
       at Test.Pages.ProjectView.ProjectView_obj1_Bindings.Update_(ProjectView obj, Int32 phase)
       at Test.Pages.ProjectView.ProjectView_obj1_Bindings.Update()
       at Test.Pages.ProjectView.<.ctor>b__6_0(FrameworkElement s, DataContextChangedEventArgs e)
  InnerException: 

(to me, it looks like the generated code just doesn't deal with the default value possibility. Btw, that __ComObject is the DependencyProperty.UnsetValue.

Edit 2: I should add that if I change the Convert function to return null instead of DependencyProperty.UnsetValue, x:Bind functions, but then neither x:Bind nor Binding do their expected job of using the FallbackValue

Jay Zuo

The FallbackValue in Binding and x:Bind is different.

In Binding, FallbackValue is the value to use when the binding is unable to return a value.

A binding uses FallbackValue for cases where the Path doesn't evaluate on the data source at all, or if attempting to set it on the source with a two-way binding throws an exception that's caught by the data binding engine. FallbackValue is also used if the source value is the dependency property sentinel value DependencyProperty.UnsetValue.

But in x:Bind, FallbackValue specifies a value to display when the source or path cannot be resolved. It can't work with DependencyProperty.UnsetValue.

As you've already know, x:Bind generates code at compile-time and it's strongly typed. When you use Converter in x:Bind, it will regard the Converter's return value of the same type as the target property and cast it like in your code:

(global::Windows.UI.Xaml.Media.ImageSource)this.LookupConverter("LocalCacheFile").Convert(obj, typeof(global::Windows.UI.Xaml.Media.ImageSource), null, null)

If you return DependencyProperty.UnsetValue in your Converter, it will throw exception as DependencyProperty.UnsetValue can't cast to ImageSource.

For your scenario, you can use TargetNullValue.

TargetNullValue is a similar property with similar scenarios. The difference is that a binding uses TargetNullValue if the Path and Source do evaluate, but the value found there is null.

For example using following code is XAML.

<Image Source="{x:Bind imageSource, TargetNullValue='ms-appx:///Assets/default.png', Converter={StaticResource LocalCacheFile}}" />

And in the Convert, return null instead of DependencyProperty.UnsetValue.

This works when running the app and the imageSource is empty. But to gain design time benefit, we still need use FallbackValue. So we can use x:Bind like following:

<Image Source="{x:Bind imageSource, TargetNullValue='ms-appx:///Assets/default.png', FallbackValue='ms-appx:///Assets/default.png', Converter={StaticResource LocalCacheFile}}" />

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

From Dev

UWP - x:Bind Mode=TwoWay throws errors without converter

From Dev

UWP x:Bind with time

From Dev

Binding to current DataContext with Converter using x:Bind

From Dev

Binding data into ListView through x:bind in UWP

From Dev

x:Bind and nested class in a UWP application

From Dev

UWP XAML x:Bind inherited interfaces are not recognized

From Dev

UWP X:Bind and Design Time Data

From Dev

String format using UWP and x:Bind

From Dev

UWP X:Bind and Design Time Data

From Dev

How to Bind the SourceUri a BitmapIcon to RadioButton in Windows 10 UWP Apps

From Dev

How can I {x:Bind} to a DataTemplate's root type in UWP?

From Dev

DXF converter in UWP

From Dev

Bind ICommand in Converter

From Dev

Bind to multiple Properties in UWP

From Dev

Bind Singleton in XAML (UWP)

From Dev

(Windows 10 UWP) How to bind Header property in PivotItem control into custom HeaderTemplate in Pivot control?

From Dev

Using x:Bind inside the GridView's ItemTemplate layout User Control in UWP

From Dev

Bind UWP ComboBox ItemsSource to Enum

From Dev

Bind Obserable Collection to MenuFlyoutSubItem in UWP

From Dev

How to bind to attached property in UWP?

From Dev

Multithreading in UWP Windows 10

From Dev

UWP on windows 10 IoT

From Dev

UWP SerialDevice.FromIdAsync throws "Element not found" (Exception from HRESULT: 0x80070490) on Windows 10

From Dev

Angular binding equivalent of a FallbackValue?

From Dev

FallBackValue in IMultiValueConverter is UnsetValue

From Dev

How to bind observable collection to canvas with converter

From Dev

How to bind a combobox with converter to a list in WPF

From Dev

Bind to arbitrary Dictionary<,> by using a converter to cast object

From Dev

How to bind a combobox with converter to a list in WPF

Related Related

  1. 1

    UWP - x:Bind Mode=TwoWay throws errors without converter

  2. 2

    UWP x:Bind with time

  3. 3

    Binding to current DataContext with Converter using x:Bind

  4. 4

    Binding data into ListView through x:bind in UWP

  5. 5

    x:Bind and nested class in a UWP application

  6. 6

    UWP XAML x:Bind inherited interfaces are not recognized

  7. 7

    UWP X:Bind and Design Time Data

  8. 8

    String format using UWP and x:Bind

  9. 9

    UWP X:Bind and Design Time Data

  10. 10

    How to Bind the SourceUri a BitmapIcon to RadioButton in Windows 10 UWP Apps

  11. 11

    How can I {x:Bind} to a DataTemplate's root type in UWP?

  12. 12

    DXF converter in UWP

  13. 13

    Bind ICommand in Converter

  14. 14

    Bind to multiple Properties in UWP

  15. 15

    Bind Singleton in XAML (UWP)

  16. 16

    (Windows 10 UWP) How to bind Header property in PivotItem control into custom HeaderTemplate in Pivot control?

  17. 17

    Using x:Bind inside the GridView's ItemTemplate layout User Control in UWP

  18. 18

    Bind UWP ComboBox ItemsSource to Enum

  19. 19

    Bind Obserable Collection to MenuFlyoutSubItem in UWP

  20. 20

    How to bind to attached property in UWP?

  21. 21

    Multithreading in UWP Windows 10

  22. 22

    UWP on windows 10 IoT

  23. 23

    UWP SerialDevice.FromIdAsync throws "Element not found" (Exception from HRESULT: 0x80070490) on Windows 10

  24. 24

    Angular binding equivalent of a FallbackValue?

  25. 25

    FallBackValue in IMultiValueConverter is UnsetValue

  26. 26

    How to bind observable collection to canvas with converter

  27. 27

    How to bind a combobox with converter to a list in WPF

  28. 28

    Bind to arbitrary Dictionary<,> by using a converter to cast object

  29. 29

    How to bind a combobox with converter to a list in WPF

HotTag

Archive