x:绑定转换器和FallbackValue不协作(UWP 10)

我有一个涉及大量代码的问题,但我把它隔离了。 如果你想要TL; DR; 进一步向下跳。 如果你想要一些上下文,这是我的情况:

我为我的绑定创建了三个数据转换器。 其中一个是“字符串前缀”:它为使用固定字符串放入的任何内容添加前缀。 在当前示例中,该固定字符串是"ms-appx:///cache/" 。 第二个将string类型转换为ImageSource ,第三个将多个转换器链接在一起。

然后我创建了一个名为LocalCacheFile的Xaml资源。 一切都按照您的想法运作。 Xaml代码看起来像这样:

  

但是,我遇到了以下问题。 如果我尝试使用FallbackValue为imageSource为空时放置占位符图像,我会在x:Bind奇怪的行为。

以下代码可以正常工作

  

  

才不是!

我已经将它分离到只有一个转换器,它是DependencyProperty.UnsetValue x:Bind似乎没有处理。

TL; DR; 这是我的字符串前缀的代码,如果我单独使用它作为测试触发相同的错误行为:

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

使用Binding时,上面的转换器按预期工作(即,如果输入字符串为空,则正确使用了回退值)。 与x:Bind一起使用时会引发类型exception。

怎么了?


编辑:有关exception的详细信息。

这是生成的代码:

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

例外细节:

 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.b__6_0(FrameworkElement s, DataContextChangedEventArgs e) InnerException: 

(对我来说,看起来生成的代码只是不处理默认值的可能性。顺便说一句, __ComObjectDependencyProperty.UnsetValue

编辑2 :我应该补充一点,如果我将Convert函数更改为返回null而不是DependencyProperty.UnsetValue, x:Bind函数,但是x:BindBinding都没有执行使用FallbackValue的预期工作

BindingFallbackValuex:Bind是不同的。

BindingFallbackValue是绑定无法返回值时使用的值。

对于Path根本不对数据源进行求值的情况,或者如果尝试使用双向绑定在源上设置它,则绑定使用FallbackValue会抛出数据绑定引擎捕获的exception。 如果源值是依赖项属性sentinel值DependencyProperty.UnsetValue,则还使用FallbackValue

但是在x:BindFallbackValue指定在无法解析源或路径时显示的值。 它无法与DependencyProperty.UnsetValue

正如您已经知道的那样, x:Bind在编译时生成代码并且它是强类型的。 当您在x:Bind使用Converter时,它会将Converter的返回值视为与target属性相同的类型,并将其Converter为您的代码:

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

如果在Converter返回DependencyProperty.UnsetValue ,它将抛出exception,因为DependencyProperty.UnsetValue无法ImageSource ConverterImageSource

对于您的方案,您可以使用TargetNullValue

TargetNullValue是一个类似的属性,具有类似的场景。 不同之处在于,如果Path和Source进行求值,则绑定使用TargetNullValue ,但在此处找到的值为null。

例如,使用以下代码是XAML。

  

Convert ,返回null而不是DependencyProperty.UnsetValue

这在运行应用程序并且imageSource为空时有效。 但为了获得设计时间的好处,我们仍然需要使用FallbackValue 。 所以我们可以使用x:Bind如下:

  

x:Bind FallBackValue实际上只用于设计时数据。 现在,让我们谈谈更重要的事情。 为什么使用x:Bind 。 通过调整IValueConverter的成本,您是否确信x:Bind值得吗? 我不是。 当我看到开发人员努力获得x:Bind工作正确绑定列表的OUTSIDE时,我的建议是切换到binding 。 每次。 在列表中,编译的绑定具有“重复”值,但是在其他任何地方,你必须向我certificate它是值得的 – 如果它是困难的话。 通常x:bind很棒。 但是在这样的情况下,像UpdateSourceTrigger这样的情况会回落或者默认为binding完全没问题。