我有一个涉及大量代码的问题,但我把它隔离了。如果你想要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:Bind
是x:Bind
。
编辑2 :我应该补充说,如果我将Convert函数更改为返回null而不是DependencyProperty.UnsetValue,Binding
函数,但是FallbackValue
和{{} 1}}完成使用class Reanalysis(object):
答案 0 :(得分:5)
FallbackValue
和Binding
中的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});
};
。