日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

[UWP]了解IValueConverter

發(fā)布時間:2025/7/14 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [UWP]了解IValueConverter 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
[UWP]了解IValueConverter 原文:[UWP]了解IValueConverter

1. 前言

IValueConverter是用于數(shù)據(jù)綁定的強大的武器,它用于Value在Binding Source和Binding Target之間的轉(zhuǎn)換。本文將介紹IValueConverter的用法及一些常用的實現(xiàn)。

2. 為什么要使用IValueConverter

假設(shè)有如下的類TestResult:

public class TestResult {public bool Passed { get; set; }}

UI需要通過Passed這個屬性決定顯示結(jié)果的文字顏色為紅色或綠色,一般初學(xué)者最常見的做法是修改TestResult類,添加一個和Passed相關(guān)的屬性:

public class TestResult {public bool Passed { get; set; }public Brush TestResultBrush{get{if (Passed)return new SolidColorBrush(Colors.Red);elsereturn new SolidColorBrush(Colors.Green);}} }

然后在XAML上綁定到這個屬性:

<TextBlock Text="Score : 60" Foreground="{Binding TestResultBrush}"/>

另一種做法是直接才Code Behind為TextBlock更改Foreground:

var testResult = DataContext as TestResult; if (testResult != null) {if (testResult.Passed)ResultElement.Foreground = new SolidColorBrush(Colors.Red);elseResultElement.Foreground = new SolidColorBrush(Colors.Green); }

兩種做法都不夠優(yōu)雅,可以指出一大堆問題:破壞了TestResult的結(jié)構(gòu),違反了開放封閉原則,令UI和數(shù)據(jù)太過耦合,太多Hard Code等。

這種情況通常都可以使用IValueConverter處理。在Binding中,IValueConverter可以用于數(shù)據(jù)呈現(xiàn)前將它轉(zhuǎn)換成新的目標值,實現(xiàn)IValueConverter需要執(zhí)行以下步驟:

  • 創(chuàng)建一個實現(xiàn)了IValueConverter接口的類類;
  • 實現(xiàn)public object Convert(object value, Type targetType, object parameter, string language)方法,該方法將數(shù)據(jù)轉(zhuǎn)換為新目標值;
  • 實現(xiàn)public object ConvertBack(object value, Type targetType, object parameter, string language),該方法執(zhí)行反向轉(zhuǎn)換,只有使用雙向綁定才需要實現(xiàn)這個方法。
  • 在這個例子里,IValueConverter的目的是將bool類型的Passed轉(zhuǎn)換成Brush,實現(xiàn)如下:

    public class BoolToBrushConverter : IValueConverter {public object Convert(object value, Type targetType, object parameter, string language){if (value is bool passed)return new SolidColorBrush(passed ? Colors.Green : Colors.Red);return null;}public object ConvertBack(object value, Type targetType, object parameter, string language){throw new NotImplementedException();} }

    在XAML中使用這個Convnerter需要先將它定義為Resource,然后Binding中指定Converter到這個已定義的Resource:

    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"><Grid.Resources><local:BoolToBrushConverter x:Key="BoolToBrushConverter"/></Grid.Resources><TextBlock Text="Score : 60" Foreground="{Binding Passed,Converter={StaticResource BoolToBrushConverter}}"/> </Grid>

    3. BoolToValueConverter

    在XAML漫長的歷史里,IValueConverter也誕生了各種奇怪的技巧,其中最常用的是BoolToValueConverter。

    public class BoolToValueConverter : IValueConverter {public object Convert(object value, Type targetType, object parameter, string language){if (value == null || (bool) value == false)return DependencyProperty.UnsetValue;return parameter;}public object ConvertBack(object value, Type targetType, object parameter, string language){return Equals(value, parameter);} }

    BoolToValueConverter靈活使用了Binding中ConverterParameter和FallbackValue兩個參數(shù),常常用于解決IValueConverter中HardCode的問題。在Binding中,FallbackValue指明了如果Binding沒法返回任何值時使用的值,在IValueConverter中返回DependencyProperty.UnsetValue即告訴Binding要使用FallbackValue的值。

    使用BoolToValueConverter解決了上述例子的Hard Code的問題,在XAML中使用如下:

    <Grid><Grid.Resources><local:BoolToValueConverter x:Key="BoolToValueConverter"/></Grid.Resources><TextBlock Text="Score : 60" Foreground="{Binding Passed,Converter={StaticResource BoolToValueConverter},ConverterParameter=Green,FallbackValue=Red}"/> </Grid>

    4. BoolToObjectConverter

    需要注意的是上面XAML中Green和Red都只是字符串,它們最終能被解析成SolidColorBrush是由于TypeConveter的支持,也就是說上述XAML語法只能用于TypeConverter支持的數(shù)據(jù)類型,而且這種寫法還是太過HardCode。如果要支持復(fù)雜類型或者對應(yīng)本地化等問題,可以將ConverterParameter和FallbackValue綁定到StaticResource :

    <Grid.Resources><SolidColorBrush Color="Green" x:Key="PassedBrush"/><SolidColorBrush Color="Red" x:Key="FailedBrush"/><local:BoolToValueConverter x:Key="BoolToValueConverter"/> </Grid.Resources> <TextBlock Text="Score : 60" Foreground="{Binding Passed,Converter={StaticResource BoolToValueConverter},ConverterParameter={StaticResource PassedBrush},FallbackValue={StaticResource FailedBrush}}"/>

    雖然看上去是很靈活,但如果有大量返回同樣值的BoolToValueConverter將會使XAML產(chǎn)生大量冗余。UWP Community Toolkit提供了一些常用的IValueConverter實現(xiàn),其中最常用的是BoolToObjectConverter。BoolToObjectConverter和BoolToValueConverter功能類似,但它提供了public object TrueValue { get; set; }和public object FalseValue { get; set; }兩個屬性,而且這兩個屬性是依賴屬性,可以使用綁定為其賦值。使用如下:

    <Grid.Resources><SolidColorBrush Color="Green" x:Key="PassedBrush"/><SolidColorBrush Color="Red" x:Key="FailedBrush"/><converters:BoolToObjectConverter x:Key="BoolToObjectConverter" TrueValue="{StaticResource PassedBrush}" FalseValue="{StaticResource FailedBrush}"/> </Grid.Resources> <TextBlock Text="Score : 60" Foreground="{Binding Passed,Converter={StaticResource BoolToObjectConverter}}"/>

    5. BoolToVisibilityConverter

    UWP Community Toolkit中提供了另一個常用的Converter:BoolToVisibilityConverter。這個Converter只是簡單地繼承了BoolToObjectConverter,并且為TrueValue和FalseValue設(shè)置了默認值:

    public BoolToVisibilityConverter() {TrueValue = Visibility.Visible;FalseValue = Visibility.Collapsed; }

    BoolToVisibilityConverter雖然簡單,但確實好用。不過從1607以后就不需要這個Converter了,微軟是這樣說的:

    從 Windows 10 版本 1607 開始,XAML 框架向 Visibility 轉(zhuǎn)換器提供內(nèi)置布爾值。 轉(zhuǎn)換器將 true 映射到 Visible 枚舉值并將 false 映射到 Collapsed,以便你可以將 Visibility 屬性綁定到布爾值,而無需創(chuàng)建轉(zhuǎn)換器。 若要使用內(nèi)置轉(zhuǎn)換器,你的應(yīng)用的最低目標 SDK 版本必須為 14393 或更高版本。

    但有時候反而需要True對應(yīng)Collapsed,于是現(xiàn)在是另一個常用Converter - BoolNegationConverter登上歷史舞臺的時候了:

    <StackPanel ><StackPanel.Resources><converters:BoolNegationConverter x:Key="BoolNegationConverter" /></StackPanel.Resources><TextBlock Text="Passed" Foreground="Green" Visibility="{Binding Passed}"/><TextBlock Text="Failed" Foreground="Red" Visibility="{Binding Passed,Converter={StaticResource BoolNegationConverter}}"/> </StackPanel>

    6. StringFormatConverter

    UWP的Binding缺少了StringFormat,這對Binding產(chǎn)生了很大影響,為彌補這個缺陷,可以使用UWP Community Toolkit中的StringFormatConverter。它的代碼也十分簡單(其實這才是ConverterParameter的正確用法):

    public object Convert(object value, Type targetType, object parameter, string language) {if (value == null){return null;}if (parameter == null){return value;}return string.Format((string)parameter, value); }

    在XAML中使用如下:

    <TextBlock Text="{Binding DoubleValue,Converter={StaticResource StringFormatConverter},ConverterParameter='{}{0:N2}'}"/> <TextBlock Text="{Binding DoubleValue,Converter={StaticResource StringFormatConverter},ConverterParameter='There are {0:N0} Items'}"/>

    結(jié)果如下:

    除了彌補StringFormat的功能,StringFormatConverter還有其它的應(yīng)用場景。

    ** TestModel.CS **

    public IEnumerable<ClickMode> ClickModes => new List<ClickMode> { ClickMode.Hover, ClickMode.Press, ClickMode.Release }; <ListBox ItemsSource="{Binding ClickModes}"><ListBox.ItemTemplate><DataTemplate><TextBlock Text="{Binding }" /></DataTemplate></ListBox.ItemTemplate> </ListBox> <ListBox ItemsSource="{Binding ClickModes}"/>

    在WPF中,以上XAML都可以正常呈現(xiàn),而在UWP中,以上XAML顯示如下:

    這種情況可以使用StringFormatConverter顯示枚舉的名稱:

    <ListBox ItemsSource="{Binding ClickModes}"><ListBox.ItemTemplate><DataTemplate><TextBlock Text="{Binding Converter={StaticResource StringFormatConverter}}" /></DataTemplate></ListBox.ItemTemplate> </ListBox>

    可以說對UWP來說StringFormatConverter十分必要。

    7. language參數(shù)

    public object Convert(object value, Type targetType, object parameter, string language)方法中的參數(shù)language通常用于本地化,例如可以創(chuàng)建一個DateTimeValueConverter:

    public class DateTimeValueConverter : IValueConverter {public object Convert(object value, Type targetType, object parameter, string language){if (value is DateTime dateTime){var culture = new CultureInfo(language);return dateTime.ToString(culture.DateTimeFormat);}return value;}public object ConvertBack(object value, Type targetType, object parameter, string language){throw new NotImplementedException();} } <TextBlock Text="{Binding Date,Converter={StaticResource DateTimeValueConverter},ConverterLanguage=en-US}"/> <TextBlock Text="{Binding Date,Converter={StaticResource DateTimeValueConverter},ConverterLanguage=zh-CN}"/>

    結(jié)果如下:

    8. targetType參數(shù)

    targetType參數(shù)指轉(zhuǎn)換后的目標類型,使用這個參數(shù)可以實現(xiàn)一個簡單的Value Converter:

    public class ValueConverter : IValueConverter {public object Convert(object value, Type targetType, object parameter, string language){return System.Convert.ChangeType(value, targetType);}public object ConvertBack(object value, Type targetType, object parameter, string language){throw new NotImplementedException();} }

    雖然代碼簡單,但它可以解決不少問題,例如 了解TypeConverter 這篇文章里提到的不能在XAML中使用decimal的問題。IValueConverter要起作用依賴于BindingSource,而在XAML中雖然很多東西都可以用來做BindingSource,例如用元素自己的Tag:

    <local:MyContentControl Tag="10.01" Amount="{Binding Converter={StaticResource ValueConverter},Path=Tag,RelativeSource={RelativeSource Mode=Self}}"/>

    或者Resources中的字符串:

    <Grid.Resources><x:String x:Key="DecimalString">10.01</x:String> </Grid.Resources> <local:MyContentControl Amount="{Binding Source={StaticResource DecimalString},Converter={StaticResource ValueConverter}}"/>

    或者更進一步寫一個字符串的包裝類:

    public class StringWrapper {public string this[string key]{get{return key;}} } <local:MyContentControl Amount="{Binding [10.01],Source={StaticResource StringWrapper},Converter={StaticResource ValueConverter}}"/>

    9. 使用IValueConverter的其它經(jīng)驗

    9.1 統(tǒng)一管理IValueConverter

    由于大部分IValueConverter行為是固定的,通常我都會把常用的IValueConverter放到一個Converters.xaml,然后在App.xaml中年合并資源字典,這樣不用重復(fù)寫創(chuàng)建Converter的xaml,也避免了重復(fù)創(chuàng)建Converter的資源消耗:

    <Application.Resources><ResourceDictionary><ResourceDictionary.MergedDictionaries><ResourceDictionary Source="Converters.xaml" /></ResourceDictionary.MergedDictionaries></ResourceDictionary> </Application.Resources>

    9.2 格式化

    Binding最讓人詬病的缺點就是它的語法太長太長太長,例如以上兩個TextBlock,在IDE中很難判斷這它們有什么不同。很多時候我都會把XAML的格式化設(shè)置成“將每個屬性分行放置”,如下圖:

    這樣上面兩個TextBlock的XAML就清晰許多了:

    不過這樣設(shè)置也并不全是好處,怎么設(shè)置具體還是看個人喜好和屏幕尺寸。

    10. 結(jié)語

    雖然IValueConverter的文章已經(jīng)不少了,但還是常常見到亂來的IValueConverter實現(xiàn),而且UWP的IValueConverter有一些改變,所以還是寫了這篇文章。

    我很想寫一些常用的,或者容易用錯的基礎(chǔ)知識,但連IValueConverter都不知不覺就寫得這么長了,實在沒勇氣寫B(tài)inding的概念,何況關(guān)于Binding 已經(jīng)有很多很實用的文章。

    我十分清楚文章寫得太長就會被“保存到Pocket”,我也想每篇文章都能在三五分鐘內(nèi)看完,但偏偏越基礎(chǔ)的概念就越能寫得長,而且寫得簡短些又會被移出博客園首頁,很難把握尺度。

    下一篇文章會盡量寫短一些。

    11. 參考

    IValueConverter Interface
    Binding Class
    深入了解數(shù)據(jù)綁定
    Converters - UWP Community Toolkit _ Microsoft Docs

    posted on 2018-11-06 14:17 NET未來之路 閱讀(...) 評論(...) 編輯 收藏

    轉(zhuǎn)載于:https://www.cnblogs.com/lonelyxmas/p/9915017.html

    總結(jié)

    以上是生活随笔為你收集整理的[UWP]了解IValueConverter的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。