[英]x:Bind Converter and FallbackValue not collaborating (UWP 10)
我有一個涉及大量代碼的問題,但我把它隔離了。 如果你想要TL; DR; 進一步向下跳。 如果你想要一點上下文,這是我的情況:
我為我的綁定創建了三個數據轉換器。 其中一個是“字符串前綴”:它為使用固定字符串放入的任何內容添加前綴。 在當前示例中,該固定字符串是"ms-appx:///cache/"
。 第二個將string
類型轉換為ImageSource
,第三個將多個轉換器鏈接在一起。
然后我創建了一個名為LocalCacheFile
的Xaml資源。 一切都按照您的想法運作。 Xaml代碼看起來像這樣:
<Image Source="{x:Bind imageSource,Converter={StaticResource LocalCacheFile}}" />
但是,我遇到了以下問題。 如果我嘗試使用FallbackValue為imageSource
為空時放置占位符圖像,我會在x:Bind
獲得奇怪的行為。
以下代碼可以正常工作 :
<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
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
一起使用時會引發類型異常。
怎么了?
編輯:有關異常的詳細信息。
這是生成的代碼:
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
。
編輯2 :我應該補充一點,如果我將Convert函數更改為返回null而不是DependencyProperty.UnsetValue, x:Bind
函數,但是x:Bind
和Binding
都沒有執行使用FallbackValue
的預期工作
Binding
的FallbackValue
和x:Bind
是不同的。
在Binding
, FallbackValue
是綁定無法返回值時使用的值。
對於Path根本不對數據源進行求值的情況,或者如果嘗試使用雙向綁定在源上設置它,則綁定使用FallbackValue會拋出數據綁定引擎捕獲的異常。 如果源值是依賴項屬性sentinel值DependencyProperty.UnsetValue,則還使用FallbackValue 。
但是在x:Bind
, FallbackValue
指定在無法解析源或路徑時顯示的值。 它無法與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
,它將拋出異常,因為DependencyProperty.UnsetValue
無法ImageSource
Converter
為ImageSource
。
對於您的方案,您可以使用TargetNullValue
。
TargetNullValue是一個類似的屬性,具有類似的場景。 不同之處在於,如果Path和Source進行求值,則綁定使用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}}" />
在x:Bind
FallBackValue
實際上僅用於設計時數據。 現在,讓我們談談更重要的事情。 為什么使用x:Bind
。 通過調整IValueConverter
的成本,您是否確信x:Bind
值得嗎? 我不是。 當我看到開發人員努力獲得x:Bind
工作正確綁定列表的OUTSIDE時,我的建議是切換到binding
。 每次。 在列表中,編譯的綁定具有“重復”值,但在其他任何地方,你必須向我證明它是值得的 - 如果它是困難的話。 通常x:bind
很棒。 但是在這種情況下,像UpdateSourceTrigger
這樣的情況會回落或默認為binding
完全正常。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.