1. 程式人生 > >WPF轉換器之通用轉換器

WPF轉換器之通用轉換器

原文: WPF轉換器之通用轉換器

WPF中的轉換器是一個非常好的資料型別轉換解決方案,實用和強大, 它的作用是將源資料轉換為WPF自身需要的型別,對資料實體沒有侵略性,會在專案工程中頻繁使用。所以掌握轉換器是WPF開發的必備技能。

我剛接觸轉換器的時候,沒有考慮通用性,每次遇到一個轉換需求都會去建立一個新的轉換器,久而久之,專案中的轉換器已多如牛毛

這當然是我無法容忍的,我決定用一種通用轉換器來代替絕大部分性質相同的轉換操作,通過約定一套引數規則來適應不同的轉換場景,達到轉換器複用的目的。

轉換器分為兩種,IValueConverter(單值轉換器)和IMultiValueConverter(多值轉換器)

單值通用轉換器 ObjectConverter

引數規則【比較值1|比較值2:true返回值:false返回值】

仔細一看,這個引數規則其實和三元表示式的含義相同,當源資料等於比較值1或者比較值2的時候,返回true返回值,否則返回false返回值

有了這個規則,就可以實現通用轉換需求了,ObjectConverter原始碼如下

 public class ObjectConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            string[] parray = parameter.ToString().ToLower().Split(':'); //將引數字元分段 parray[0]為比較值,parray[1]為true返回值,parray[2]為false返回值
            if (value == null)
                return parray[2];  //如果資料來源為空,預設返回false返回值
            if (parray[0].Contains("|"))  //判斷有多個比較值的情況
                return parray[0].Split('|').Contains(value.ToString().ToLower()) ? parray[1] : parray[2];  //多值比較
            return parray[0].Equals(value.ToString().ToLower()) ? parray[1] : parray[2];  //單值比較
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            var returnValue = "otherValue";
            string[] parray = parameter.ToString().ToLower().Split(':');
            if (value == null)
                return returnValue;
            var valueStr = value.ToString().ToLower();
            if (valueStr != parray[1])
                return returnValue;
            else
                return parray[0].Contains('|') ? parray[0].Split('|')[0] : parray[0];
        }
    }

 ObjectConverter的使用

1 <converter:ObjectConverter x:Key="objConverter"/>
2 
3 <Border Visibility="{Binding PanelStatus,  Converter={StaticResource objConverter},ConverterParameter=true:Visible:Collapsed}">
4 
5 <Border Background="{Binding BgColor,  Converter={StaticResource objConverter},ConverterParameter=1:Red:Blue}
"> 6 7 <TextBlock Text="{Binding Type, Converter={StaticResource objConverter},ConverterParameter=1|2:VIP會員:普通會員}"/>

 

多值通用轉換器 MultiObjectConverter

引數規則【各組比較值:比較條件(&amp;或|):true返回值:false返回值:返回值型別列舉】

多值轉換器的引數規則略顯麻煩,但是也和三元表示式類似,只不過多了比較條件和返回值列舉型別,這裡有人要問了為什麼單值轉換器不需要宣告返回值列舉而多值轉換器需要,這是因為多值轉換器的返回值不返回實際型別的話,返回型別會失效,WPF的預設轉換器似乎沒有起到作用。這個問題我也正在研究,所以先定義一個返回值列舉用來轉換返回值的型別。姑且算一個臨時解決方案吧

 1 public class MultiObjectConverter : IMultiValueConverter
 2     {
 3         /// <summary>
 4         /// 多值轉換器
 5         /// </summary>
 6         /// <param name="values">引數值陣列</param>
 7         /// <param name="parameter">
 8         /// <para>引數</para>
 9         /// <para>各組比較值:比較條件(&amp;或|):true返回值:false返回值:返回值型別列舉</para>
10         /// <para>v1;v2-1|v2-2;v3:&amp;:Visible:Collapsed:1</para>
11         /// </param>
12         /// <returns></returns>
13         public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
14         {
15             string[] param = parameter.ToString().ToLower().Split(':');   //將引數字串分段
16             string[] compareValues = param[0].Split(';'); //將比較值段分割為陣列
17             if (values.Length != compareValues.Length)  //比較源資料和比較引數個數是否一致
18                 return ConvertValue(param[3], param[4]);
19             var trueCount = 0; //滿足條件的結果數量
20             var currentValue = string.Empty;
21             IList<string> currentParamArray = null;
22             for (var i = 0; i < values.Length; i++)
23             {
24                 currentValue = values[i] != null ? values[i].ToString().ToLower() : string.Empty;
25                 if (compareValues[i].Contains("|"))
26                 {
27                     //當前比較值段包含多個比較值
28                     currentParamArray = compareValues[i].Split('|'); 
29                     trueCount += currentParamArray.Contains(currentValue) ? 1 : 0;  //滿足條件,結果+1
30                 }
31                 else
32                 {
33                     trueCount += compareValues[i].Equals(currentValue) ? 1 : 0;  //滿足條件,結果+1
34                 }
35             }
36             currentParamArray = null;
37             currentValue = string.Empty;
38             var compareResult = param[1].Equals("&") ?
39                 trueCount == values.Length :
40                 trueCount > 0;   //判斷比較結果
41             return ConvertValue(compareResult ? param[2] : param[3], param[4]);
42         }
43 
44         public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
45         {
46             throw new NotImplementedException();
47         }
48 
49         private object ConvertValue(string result, string enumStr)
50         {
51             var convertResult = (ConvertResult)int.Parse(enumStr);
52             if (convertResult == ConvertResult.顯示型別)
53                 return result.Equals("collapsed") ? Visibility.Collapsed : Visibility.Visible;
54             if (convertResult == ConvertResult.布林型別)
55                 return System.Convert.ToBoolean(result);
56             return null;  //後續自行擴充套件
57         }
58 
59         private enum ConvertResult
60         {
61             顯示型別 = 1,
62             布林型別 = 2,
63             字串型別 = 3,
64             整型 = 4,
65             小數型 = 5,
66             畫刷型別 = 6,
67             樣式型別 = 7,
68             模板型別 = 8
69         }
70     }

MulitObjectConverter的使用

1 <TextBlock Text="test">
2    <TextBlock.Visibility>
3         <MultiBinding Converter="{StaticResource mobjConverter}"
4                       ConverterParameter="1|2;true:|:Visible:Collapsed:1">
5              <Binding Path="Filed1"/>
6              <Binding Path="Filed2"/>
7         </MultiBinding>
8     </TextBlock.Visibility>
9 </TextBlock>    

單值通用轉換器和多值通用轉換器已經講完了,讀者可以根據自己的需求定製ConverterParameter的規則,實現靈活擴充套件。歡迎入群交流372754241