小序:
咳咳,我知道這個標題不太好讓人明白。
它的意思是這樣——我們知道,用C#代碼編寫的類也可以在XAML文檔裏聲明實例,聲明之後我們可以使用XAML的Attribute對實例的
Property進行賦值。但XAML標籤的Attribute只能接受string類型的值,如果像int、double這類簡單的值還好辦,如果是復
雜的值呢?我們應該怎麼辦?
正文:
我們知道,XAML標籤會對應一個實例。如果在XAML裏初始化實例的屬性,我們有兩種語法可以選擇:
- 直接使用Attribute="Value"的方法
- 屬性元素(Property Element)方法
今天我們討論的核心就是——第一種方法是如何實現的。
先看一個例子。我爲一個Grid設置了矢量漸變畫刷:
- <Grid>
- <Grid.Background>
- <LinearGradientBrush StartPoint="0,0" EndPoint="1,1">
- <GradientStop Offset="0" Color="White"/>
- <GradientStop Offset="0.5" Color="LawnGreen"/>
- <GradientStop Offset="1" Color="White"/>
- </LinearGradientBrush>
- </Grid.Background>
- </Grid>
效果是這樣:
請大家注意StartPoint="0,0" EndPoint="1,1這兩個Attribute,它們實際上對應的是實例的兩個屬性。如果查看MSDN,你會發現這兩個屬性的數據類型是Point而不是String。那麼,一個string類型值是如何被轉換成Point類型值的呢?
讓我們自己動手DIY一個!
首先,我們準備了一個類:
- public class Human
- {
- public string Name { get; set; }
- public Human Child { get; set; }
- }
這個類具有兩個屬性
-
string類型的Name
-
Human類型的Child
現在我的期望是,如果我在XAML裏這樣寫:
- <Window.Resources>
- <local:Human x:Key="human" Child="ABC"/>
- </Window.Resources>
則能夠爲Human實例的Child賦一個Human類型的值,並且Child.Name就是這個字符串的值。
我們先看看直接寫行不行……
我在UI上添加了一個按鈕button1,並在它的Click事件處理器裏寫上:
- private void button1_Click(object sender, RoutedEventArgs e)
- {
- Human h = (Human)this.FindResource("human");
- MessageBox.Show(h.Child.Name);
- }
編譯沒有問題,但在我點擊按鈕之後程序拋出異常——告訴我Child不存在。那我們應該怎麼做呢?
辦法是使用TypeConverter和TypeConverterAttribute這兩個類。
首先,我們要從TypeConverter類派生出自己的類,並重寫它的一個ConvertFrom方法。這個方法有一個參數名爲value,這個值就是在XAML文檔裏爲它設置的值。我們要做的就是把這個值“翻譯”成合適類型的值、賦給對象的屬性:
- public class StringToHumanTypeConverter : TypeConverter
- {
- public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
- {
- if (value is string)
- {
- Human h = new Human();
- h.Name = value as string;
- return h;
- }
- return base.ConvertFrom(context, culture, value);
- }
- }
有了這個類還不夠,還要使用TypeConverterAttribute這個特徵類把StringToHumanTypeConverter這個類“粘貼”到作爲目標的Human類上。
- [TypeConverterAttribute(typeof(StringToHumanTypeConverter))]
- public class Human
- {
- public string Name { get; set; }
- public Human Child { get; set; }
- }
因爲特徵類在使用的時候可以省略Attribute這個詞,所以我們也可以寫成:
- [TypeConverter(typeof(StringToHumanTypeConverter))]
- public class Human
- {
- public string Name { get; set; }
- public Human Child { get; set; }
- }
但這樣寫,我們需要認清寫在方括號裏的是TypeConverterAttribute而不是TypeConverter。
完成之後,再次點擊按鈕,我們想要的結果就出來了!
TO BE CONTINUED...