深入浅出WPF——如何实现类的Property与标签的Attribute映射
2009-01-07 15:16
603 查看
小序:
咳咳,我知道这个标题不太好让人明白。
它的意思是这样——我们知道,用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>
效果是这样:
[align=left]请大家注意StartPoint="0,0" EndPoint="1,1这两个Attribute,它们实际上对应的是实例的两个属性。如果查看MSDN,你会发现这两个属性的数据类型是Point而不是String。那么,一个string类型值是如何被转换成Point类型值的呢?[/align]
[align=left] [/align]
[align=left]让我们自己动手DIY一个![/align]
[align=left] [/align]
[align=left]首先,我们准备了一个类:[/align]
[align=left] [/align]
public class Human
{
public string Name { get; set; }
public Human Child { get; set; }
}
[align=left]这个类具有两个属性[/align]
[align=left]string类型的Name[/align]
[align=left]Human类型的Child[/align]
[align=left]现在我的期望是,如果我在XAML里这样写:[/align]
<Window.Resources>
<local:Human x:Key="human" Child="ABC"/>
</Window.Resources>
[align=left]则能够为Human实例的Child赋一个Human类型的值,并且Child.Name就是这个字符串的值。[/align]
[align=left]我们先看看直接写行不行……[/align]
[align=left]我在UI上添加了一个按钮button1,并在它的Click事件处理器里写上:[/align]
private void button1_Click(object sender, RoutedEventArgs e)
{
Human h = (Human)this.FindResource("human");
MessageBox.Show(h.Child.Name);
}
[align=left]编译没有问题,但在我点击按钮之后程序抛出异常——告诉我Child不存在。那我们应该怎么做呢?[/align]
[align=left]办法是使用TypeConverter和TypeConverterAttribute这两个类。[/align]
[align=left] [/align]
[align=left]首先,我们要从TypeConverter类派生出自己的类,并重写它的一个ConvertFrom方法。这个方法有一个参数名为value,这个值就是在XAML文档里为它设置的值。我们要做的就是把这个值“翻译”成合适类型的值、赋给对象的属性:[/align]
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; }
}
[align=left]但这样写,我们需要认清写在方括号里的是TypeConverterAttribute而不是TypeConverter。[/align]
[align=left] [/align]
[align=left]完成之后,再次点击按钮,我们想要的结果就出来了![/align]
[align=left] [/align]
[align=left] [/align]
[align=left] [/align]
[align=left]TO BE CONTINUED...[/align]
咳咳,我知道这个标题不太好让人明白。
它的意思是这样——我们知道,用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>
效果是这样:
[align=left]请大家注意StartPoint="0,0" EndPoint="1,1这两个Attribute,它们实际上对应的是实例的两个属性。如果查看MSDN,你会发现这两个属性的数据类型是Point而不是String。那么,一个string类型值是如何被转换成Point类型值的呢?[/align]
[align=left] [/align]
[align=left]让我们自己动手DIY一个![/align]
[align=left] [/align]
[align=left]首先,我们准备了一个类:[/align]
[align=left] [/align]
public class Human
{
public string Name { get; set; }
public Human Child { get; set; }
}
[align=left]这个类具有两个属性[/align]
[align=left]string类型的Name[/align]
[align=left]Human类型的Child[/align]
[align=left]现在我的期望是,如果我在XAML里这样写:[/align]
<Window.Resources>
<local:Human x:Key="human" Child="ABC"/>
</Window.Resources>
[align=left]则能够为Human实例的Child赋一个Human类型的值,并且Child.Name就是这个字符串的值。[/align]
[align=left]我们先看看直接写行不行……[/align]
[align=left]我在UI上添加了一个按钮button1,并在它的Click事件处理器里写上:[/align]
private void button1_Click(object sender, RoutedEventArgs e)
{
Human h = (Human)this.FindResource("human");
MessageBox.Show(h.Child.Name);
}
[align=left]编译没有问题,但在我点击按钮之后程序抛出异常——告诉我Child不存在。那我们应该怎么做呢?[/align]
[align=left]办法是使用TypeConverter和TypeConverterAttribute这两个类。[/align]
[align=left] [/align]
[align=left]首先,我们要从TypeConverter类派生出自己的类,并重写它的一个ConvertFrom方法。这个方法有一个参数名为value,这个值就是在XAML文档里为它设置的值。我们要做的就是把这个值“翻译”成合适类型的值、赋给对象的属性:[/align]
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; }
}
[align=left]但这样写,我们需要认清写在方括号里的是TypeConverterAttribute而不是TypeConverter。[/align]
[align=left] [/align]
[align=left]完成之后,再次点击按钮,我们想要的结果就出来了![/align]
[align=left] [/align]
[align=left] [/align]
[align=left] [/align]
[align=left]TO BE CONTINUED...[/align]
相关文章推荐
- 深入浅出WPF——如何实现类的Property与标签的Attribute映射
- IE 混淆了 DOM 对象属性(property)及 HTML 标签属性(attribute),造成了对 setAttribute、getAttribute 的不正确实现
- [转]如何实现类的Property与标签的Attribute映射
- [WPF/Silverlight]让INotifyPropertyChanged的实现更优雅一些
- JS实现60s倒计时(亲测有效),及span标签如何使用和禁用onclick事件
- [转]如何实现彩色标签云 WP插件
- 如何实现页面上的超链接指向这个嵌入的网页?/ IFRAME标签的使用。
- Hibernate多对多的关联映射(如何配置,代码实现)
- Hibernate如何实现数据表映射的继承关系
- WPF(四)Application3:如何实现单实例的应用程序(Single Instance)
- 如何在JSP页面中使用JSTL标签实现if-else判断
- Scala深入浅出实战经典 第82讲:Scala中List的ListBuffer是如何实现高效的遍历计算的?
- WPF如何实现拖拽打开文件(将文件拖进窗体打开)
- WPF如何实现窗体透明——Opacity
- WPF:如何实现单实例的应用程序(Single Instance)
- 如何实现INotifyPropertyChanged接口(C#)
- jquery如何改变html标签的样式(两种实现方法)
- Javascript常见问题及解决(二)如何实现浏览器内多个标签页之间的通信?
- 如何在zencart里实现多标签标签云效果
- 如何实现映射