WPF轉換器之通用轉換器

WPF中的轉換器是一個很是好的數據類型轉換解決方案,實用和強大, 它的做用是將源數據轉換爲WPF自身須要的類型,對數據實體沒有侵略性,會在項目工程中頻繁使用。因此掌握轉換器是WPF開發的必備技能。數組

我剛接觸轉換器的時候,沒有考慮通用性,每次遇到一個轉換需求都會去建立一個新的轉換器,長此以往,項目中的轉換器已多如牛毛spa

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

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

單值通用轉換器 ObjectConverter開發

參數規則【比較值1|比較值2:true返回值:false返回值】字符串

仔細一看,這個參數規則其實和三元表達式的含義相同,當源數據等於比較值1或者比較值2的時候,返回true返回值,不然返回false返回值get

有了這個規則,就能夠實現通用轉換需求了,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的使用string

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會員:普通會員}"/>

 

多值通用轉換器 MultiObjectConverterit

參數規則【各組比較值:比較條件(&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

相關文章
相關標籤/搜索