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

时间:2016-02-04 12:18:11

标签: c# winrt-xaml uwp winrt-xaml-toolkit

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

我为绑定创建了三个数据转换器。其中一个是“字符串前缀”:它为使用固定字符串放入的任何内容添加前缀。在当前示例中,该固定字符串为ImageSource。第二个将LocalCacheFile类型转换为<Image Source="{x:Bind imageSource,Converter={StaticResource LocalCacheFile}}" /> ,第三个将多个转换器链接在一起。

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

x:Bind

但是,我遇到了以下问题。如果我尝试使用FallbackValue为<Image Source="{Binding imageSource,FallbackValue='ms-appx:///Assets/default.png',Converter={StaticResource LocalCacheFile}}" /> 为空时放置占位符图像,我只会在<Image Source="{x:Bind imageSource,FallbackValue='ms-appx:///Assets/default.png',Converter={StaticResource LocalCacheFile}}" /> 中出现奇怪的行为。

以下代码正常运作

DependencyProperty.UnsetValue

但是

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似乎没有处理。

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

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); } } 时,上述转换器的工作方式正如您所期望的那样(即,如果输入字符串为空,则正确使用了回退值)。与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: 一起使用时会引发类型异常。

这是怎么回事?

修改:有关例外的详细信息。

这是生成的代码:

__ComObject

异常详情:

DependencyProperty.UnsetValue

(对我而言,生成的代码看起来似乎没有处理默认值的可能性。顺便说一下,x:Bindx:Bind

编辑2 :我应该补充说,如果我将Convert函数更改为返回null而不是DependencyProperty.UnsetValue,Binding函数,但是FallbackValue和{{} 1}}完成使用class Reanalysis(object):

的预期工作

2 个答案:

答案 0 :(得分:5)

FallbackValueBinding中的x:Bind不同。

Binding中,FallbackValue是绑定无法返回值时使用的值。

  

绑定使用 FallbackValue 来处理Path根本不评估数据源的情况,或尝试使用双向设置源的情况绑定抛出数据绑定引擎捕获的异常。如果源值是依赖项属性sentinel值DependencyProperty.UnsetValue,也会使用 FallbackValue

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

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

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

如果您在DependencyProperty.UnsetValue中返回Converter,则会引发异常,因为DependencyProperty.UnsetValue无法投放到ImageSource

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

  

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

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

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

Convert中,返回null而不是DependencyProperty.UnsetValue

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

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

答案 1 :(得分:3)

x:Bind中,FallBackValue实际上仅用于设计时数据。现在,让我们谈谈更重要的事情。为什么要使用x:Bind。通过调整IValueConverter的成本,你确信x:Bind值得吗?我不是。当我看到开发人员努力让x:Bind正常工作以绑定列表的OUTSIDE时,我建议切换到binding。每次。在列表中,编译的绑定有一个&#34;重复&#34;价值,但在其他任何地方,你必须向我证明这是值得的努力 - 如果它是困难的。通常x:bind很棒。但在这种情况下,像UpdateSourceTrigger这样的案件可能会落后于binding或者默认为image.onLoad = function() { var fabric_canvas = new fabric.Canvas('canvas1'); fabric_canvas.setDimensions({width:image.width, height:image.height}); };