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
TypeException
? – Yungyunickparamater
to provide the fallback value, rather than the actualFallbackValue
of the binding itself? – Yungyunick