C# x:绑定转换器和回退值不协作(UWP 10)

C# x:绑定转换器和回退值不协作(UWP 10),c#,winrt-xaml,uwp,winrt-xaml-toolkit,C#,Winrt Xaml,Uwp,Winrt Xaml Toolkit,我有一个问题,涉及到一堆代码,但我已经把它隔离了。如果你想要一个TL;博士再往下跳。如果你想了解一些情况,以下是我的情况: 我已经为绑定创建了三个数据转换器。其中一个是“字符串前缀器”:它以固定字符串作为输入内容的前缀。在当前示例中,该固定字符串为“ms-appx:///cache/“。第二个将字符串类型转换为图像源,第三个将多个转换器链接在一起 然后我创建了一个称为LocalCacheFile的Xaml资源。一切都按照你的想法进行。这方面的Xaml代码如下所示: <Image Sourc

我有一个问题,涉及到一堆代码,但我已经把它隔离了。如果你想要一个TL;博士再往下跳。如果你想了解一些情况,以下是我的情况:

我已经为绑定创建了三个数据转换器。其中一个是“字符串前缀器”:它以固定字符串作为输入内容的前缀。在当前示例中,该固定字符串为
“ms-appx:///cache/“
。第二个将
字符串
类型转换为
图像源
,第三个将多个转换器链接在一起

然后我创建了一个称为
LocalCacheFile
的Xaml资源。一切都按照你的想法进行。这方面的Xaml代码如下所示:

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

使用
绑定时,上述转换器的工作方式与您预期的相同(即,如果输入字符串为空,则正确使用回退值)。与
x:Bind
一起使用时会引发类型异常

这是怎么回事


编辑:有关异常的详细信息

这是生成的代码:

        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);
            }
        }
private void Update\u project\u imageSource(全局::System.String obj,int阶段)
{

如果((阶段)和((1在
Binding
x:Bind
中的
FallbackValue
不同

绑定中
,是绑定无法返回值时要使用的值

绑定使用FallbackValue用于根本不对数据源求值的情况,或者如果试图使用双向绑定在源上设置它,会引发数据绑定引擎捕获的异常。如果源值是依赖属性sentinel值,也会使用FallbackValue

但是在
x:Bind
中,指定了当源或路径无法解析时要显示的值。它不能使用
DependencyProperty.UnsetValue

正如您已经知道的,
x:Bind
在编译时生成代码,并且它是强类型的。当您在
x:Bind
中使用
Converter
时,它会将类型相同的
Converter
返回值视为目标属性,并在代码中强制转换它:

(global::Windows.UI.Xaml.Media.ImageSource)this.LookupConverter("LocalCacheFile").Convert(obj, typeof(global::Windows.UI.Xaml.Media.ImageSource), null, null)
如果在
转换器中返回
dependencProperty.UnsetValue
,它将抛出异常作为
dependencProperty.UnsetValue
无法转换到
ImageSource

对于您的场景,可以使用
TargetNullValue

TargetNullValue是一个具有类似场景的类似属性。不同之处在于,如果路径和源确实求值,但在那里找到的值为null,则绑定使用TargetNullValue

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

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

x:Bind
中,
FallBackValue
实际上只用于设计时数据。现在,让我们来谈谈更重要的事情。为什么要使用
x:Bind
。以开发
IValueConverter
的成本为代价,你确信
x:Bind
值得吗?我不相信。当我看到开发人员努力获得
x:Bind>时
要正确处理列表外的绑定,我的建议是切换到
绑定
。每次。在列表内,编译的绑定有一个“重复”值,但在其他任何地方,您都必须向我证明,这是值得努力的-如果这是其他困难的话。通常
x:bind
非常好。但是在这样的情况下,以及
UpdateSourceTrigger
这样的情况下,返回到
绑定或默认为
绑定是非常好的。

您能添加关于
typexe>的详细信息吗Option
?我添加了异常信息。不是作为解决方案,而是作为解决方法:使用
参数
提供回退值,而不是绑定本身的实际
回退值如何?是的,我也尝试过。回退值有两个优点:运行时和设计时优势。最后,我刚刚ted对运行时解决方案进行了胡乱的研究(即通过复制占位符图像),特别是考虑到我没有预见到数据模型的任何缩放问题。也就是说,我认为这是一个真正的错误。x:Bind的另一个烦恼(我必须链接转换器的原因):转换后,类型强制将丢失。您可以绑定到数据为字符串类型的源属性,但如果转换器输出字符串,则无法绑定。这很烦人。我同意这是一个错误。但我有点好奇,为什么会有COM_对象…请确保向报告此错误!如果在那里创建了任何响应,请确保向上报告请注明此问题的日期。谢谢,此解决方案非常好!我不知道它是如何发生的,但我直到一年后才看到它。我已将其标记为已解决,很抱歉延迟!这是一个很好的示例,说明了为什么在UWP中,我们不从转换器返回
未设置值
        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.<.ctor>b__6_0(FrameworkElement s, DataContextChangedEventArgs e)
  InnerException: 
(global::Windows.UI.Xaml.Media.ImageSource)this.LookupConverter("LocalCacheFile").Convert(obj, typeof(global::Windows.UI.Xaml.Media.ImageSource), null, null)
<Image Source="{x:Bind imageSource, TargetNullValue='ms-appx:///Assets/default.png', Converter={StaticResource LocalCacheFile}}" />
<Image Source="{x:Bind imageSource, TargetNullValue='ms-appx:///Assets/default.png', FallbackValue='ms-appx:///Assets/default.png', Converter={StaticResource LocalCacheFile}}" />