WPF学习:4.类型转换和标记扩展
在上一章,主要介绍了Border和Brush,这一章主要介绍下类型转换和标记扩展。相关代码链接如下:
http://files.cnblogs.com/keylei203/4.WPFSampleDemo.zip
Type Converter
在XAML中,所有的对象都是字符串,XAML解析器通过类型转换器跨越字符和非字符的鸿沟,类型转换器就是将这些字符串转换为相应的CLR对象。
所有类型转换器都是派生自TypeConverter,派生的类有100多个,比较常用的比如BrushConverter,就可以实现从字符串转换成相应的画刷,又如Margin,Margin=10,20,0,30,解析器会自动按照左,上,右,下的顺序将数据转换为宽度数据。
TypeConverter都4个重要方法是CanConvertTo,CanConvertFrom,ConvertTo和ConvertFrom。
CanConvertTo:检测CLR对象是否能转换成相应的字符串。
CanConvertFrom:检测能否从字符串转换成相应的CLR对象。
ConvertTo:将CLR对象转换成相应的字符串。
ConvertFrom:从字符串转换成相应的CLR对象。
XAML解析器解析任何属性值时都包含两部分信息:Value Type-决定了字符串转化后的类型。Actual Value-属性值大小。解析器通过两个步骤来查找类型转换器:
(1)检查属性声明查找TypeConvert特性,如窗口的Width和Height属性(派生自FrameworkElement)前面都会声明一个类型转换器。下面代码通过Reflector查看到的FrameworkElement的源代码片段:
1 public class FrameworkElement.... 2 { 3 [......TypeConverter(typeof(LengthConverter))] 4 public double Height{get;set;} 5 [......TypeConverter(typeof(LengthConverter))] 6 public double Width{get;set;} 7 }
(2)如果属性声明中没有TypeConverter特征,XAML解析器会检查对应的数据类型的类的声明。如按钮Background属性声明是Brush,并在Brush类头部就声明了一个BrushConverter转换器,这样在设置Background属性时XAML解析器会自动应用该转换器。下面代码为用过Reflector查看到的Brush片段。
1 [......TypeConverter(typeof(BrushConverter))...... 2 public abstract class Brush:Animatable
Custom TypeConverter
建立一个CustomTypeConverter必须建立一个新类,在我的例子中,我建立了一个具有Latitude和Longitude属性的类,这个类实现地理位置。
1 [global::System.ComponentModel.TypeConverter(typeof(GeoPointConverter))] 2 public class GeoPointItem 3 { 4 public double Latitude { get; set; } 5 public double Longitude { get; set; } 6 7 public GeoPointItem() 8 { 9 } 10 11 public GeoPointItem(double lat, double lon) 12 { 13 this.Latitude = lat; 14 this.Longitude = lon; 15 } 16 17 public static GeoPointItem Parse(string data) 18 { 19 if (string.IsNullOrEmpty(data)) return new GeoPointItem(); 20 21 string[] items = data.Split(','); 22 if (items.Count() != 2) 23 throw new FormatException("GeoPoint should have both latitude 24 and longitude"); 25 26 double lat, lon; 27 try 28 { 29 lat = Convert.ToDouble(items[0]); 30 } 31 catch (Exception ex) { 32 throw new FormatException("Latitude value cannot be converted", ex); 33 } 34 35 try 36 { 37 lon = Convert.ToDouble(items[1]); 38 } 39 catch (Exception ex) { 40 throw new FormatException("Longitude value cannot be converted", ex); 41 } 42 43 return new GeoPointItem(lat, lon); 44 } 45 46 public override string ToString() 47 { 48 return string.Format("{0},{1}", this.Latitude, this.Longitude); 49 } 50 }
上面的类具有Latitude和Longitude两个double型属性,我重写了ToString(),这对于得到一个完整的字符串来说是非常重要的,Parse方法能够解析字符串格式到地理坐标。
接下俩就是为这个类写一个TypeConverter,将实现4个方法,关键的是ConvertFrom方法,通过GeoPointItem静态方法Parse将字符串转化为正确的类型。
1 public class GeoPointConverter : global::System.ComponentModel.TypeConverter 2 { 3 4 //should return true if sourcetype is string 5 public override bool CanConvertFrom( 6 System.ComponentModel.ITypeDescriptorContext context, Type sourceType) 7 { 8 if (sourceType is string) 9 return true; 10 return base.CanConvertFrom(context, sourceType); 11 } 12 //should return true when destinationtype if GeopointItem 13 public override bool CanConvertTo( 14 System.ComponentModel.ITypeDescriptorContext context, Type destinationType) 15 { 16 if (destinationType is string) 17 return true; 18 19 return base.CanConvertTo(context, destinationType); 20 } 21 //Actual convertion from string to GeoPointItem 22 public override object ConvertFrom( 23 System.ComponentModel.ITypeDescriptorContext context, 24 System.Globalization.CultureInfo culture, object value) 25 { 26 if (value is string) 27 { 28 try 29 { 30 return GeoPointItem.Parse(value as string); 31 } 32 catch (Exception ex) 33 { 34 throw new Exception(string.Format( 35 "Cannot convert '{0}' ({1}) because {2}", value, value.GetType(), ex.Message), ex); 36 } 37 } 38 39 return base.ConvertFrom(context, culture, value); 40 } 41 42 //Actual convertion from GeoPointItem to string 43 public override object ConvertTo( 44 System.ComponentModel.ITypeDescriptorContext context, 45 System.Globalization.CultureInfo culture, object value, Type destinationType) 46 { 47 if(destinationType == null) 48 throw new ArgumentNullException("destinationType"); 49 50 GeoPointItem gpoint = value as GeoPointItem; 51 52 if(gpoint != null) 53 if (this.CanConvertTo(context, destinationType)) 54 return gpoint.ToString(); 55 56 return base.ConvertTo(context, culture, value, destinationType); 57 } 58 }
接下去是使用这个类型转化器的时候了,建立一个用户控件,添加一个GeoPoint属性:
1 <Grid> 2 <Grid.RowDefinitions> 3 <RowDefinition/> 4 <RowDefinition/> 5 </Grid.RowDefinitions> 6 <Grid.ColumnDefinitions> 7 <ColumnDefinition/> 8 <ColumnDefinition/> 9 </Grid.ColumnDefinitions> 10 <TextBlock Text="Latitude" Grid.Row="0" Grid.Column="0"></TextBlock> 11 <TextBox x:Name="txtlat" MinWidth="40" Grid.Row="0" Grid.Column="1" 12 TextChanged="txtlat_TextChanged"/> 13 <TextBlock Text="Longitude" Grid.Row="1" Grid.Column="0"></TextBlock> 14 <TextBox x:Name="txtlon" MinWidth="40" Grid.Row="1" Grid.Column="1" 15 TextChanged="txtlon_TextChanged"/> 16 </Grid>
控件拥有两个Textboxes显示Latutude和Longitude,当textBox内容发生修改时,GeopointItem值也会相应更改。
1 public partial class GeoPoint : UserControl 2 { 3 public static readonly DependencyProperty GeoPointValueProperty = 4 DependencyProperty.Register("GeoPointValue", typeof(GeoPointItem), 5 typeof(GeoPoint), new PropertyMetadata(new GeoPointItem(0.0, 0.0))); 6 public GeoPoint() 7 { 8 InitializeComponent(); 9 } 10 11 public GeoPointItem GeoPointValue 12 { 13 get 14 { 15 return this.GetValue(GeoPointValueProperty) as GeoPointItem; 16 } 17 set 18 { 19 this.SetValue(GeoPointValueProperty, value); 20 } 21 } 22 23 private void txtlat_TextChanged(object sender, TextChangedEventArgs e) 24 { 25 GeoPointItem item = this.GeoPointValue; 26 27 item.Latitude = Convert.ToDouble(txtlat.Text); 28 this.GeoPointValue = item; 29 } 30 31 private void txtlon_TextChanged(object sender, TextChangedEventArgs e) 32 { 33 GeoPointItem item = this.GeoPointValue; 34 35 item.Longitude = Convert.ToDouble(txtlon.Text); 36 this.GeoPointValue = item; 37 } 38 39 private void UserControl_Loaded(object sender, RoutedEventArgs e) 40 { 41 GeoPointItem item = this.GeoPointValue; 42 this.txtlat.Text = item.Latitude.ToString(); 43 this.txtlon.Text = item.Longitude.ToString(); 44 45 } 46 }
对于窗体,需要添加这个自定义控件,设置它的初值。
1 <converter:GeoPoint x:Name="cGeoPoint" GeoPointValue="60.5,20.5" />
Markup Extension
MarkupExtension提供一个XAML属性的灵活性,XAML中只要属性值被{}括起,XAML解析器就会认为这是一个扩展标记,而不是一个普通的字符串。
Extension
在System.Windows.Markup命名空间内已经有了一些标记扩展:
NullExtention
是XAML提供的一种标记扩展,表示一个空值,这可能是所有标记扩展中最简单的了。
Content = "{x:Null}"
ArrayExtension
用来创建一个数组集合。
Values = {x:Array Type=sys:String}
StaticExtension
返回一个静态字段和引用
Text="{x:Static Member=local:MyClass.StaticProperty}"
当你定义一个MyClass类的静态属性时,你可以使用它来将属性自动的赋给Text。
TypeExtension
TargetType="{x:Type Button}"
获得一个button对象的类型
Reference
Text="{x:Reference Name=Myobject}"
引用一个在XAML中声明的对象,.NET4.0特性
StaticResourceExtension
1 <Grid.Resources> 2 3 <Color x:Key="rKeyBlack">Black</Color> 4 <SolidColorBrush Color="{StaticResource rKeyBlack}" x:Key="rKeyBlackBrush"/> 5 6 7 </Grid.Resources> 8 9 <TextBlock Background="{StaticResource ResourceKey=rKeyBlackBrush}" />
DynamicResourceExtension
<TextBlock Background="{DynamicResource ResourceKey=rKeyBlackBrush}" />
似水无痕:http://www.cnblogs.com/keylei203/
转载于:https://www.cnblogs.com/keylei203/archive/2013/03/12/2956379.html
WPF学习:4.类型转换和标记扩展相关推荐
- 2.6 wpf标记扩展
1.什么是标记扩展?为什么要有标记扩展? 标记扩展是扩展xmal的表达能力 为了克服现存的类型转换机制存在的 常用的标记扩展有如下: x:Array 代表一个.net数组,它的子元素都是数组元素.它必 ...
- wpf中xaml的类型转换器与标记扩展
wpf中xaml的类型转换器与标记扩展 原文:wpf中xaml的类型转换器与标记扩展 这篇来讲wpf控件属性的类型转换器 类型转换器 类型转换器在asp.net控件中已经有使用过了,由于wpf的界面是 ...
- [No0000130]WPF 4.5使用标记扩展订阅事件
自从我上次写到关于标记扩展的时候已经有一段时间了...... Visual Studio 11 Developer Preview的发布给WPF带来了一些新功能,让我有理由再次使用它们.我要在这里讨论 ...
- WPF - 自定义标记扩展
在使用WPF进行编程的过程中,我们常常需要使用XAML的标记扩展:{Binding},{x:Null}等等.那么为什么WPF提供了XAML标记扩展这一功能,我们又如何创建自定义的标记扩展呢.这就是本文 ...
- [No000013F]WPF学习之X名称空间详解
X名称空间里面的成员(如X:Name,X:Class)都是写给XAML编译器看的.用来引导XAML代码将XAML代码编译为CLR代码. 4.1X名称空间里面到底都有些什么? x名称空间映射的是:htt ...
- WPF学习之深入浅出话模板
图形用户界面应用程序较之控制台界面应用程序最大的好处就是界面友好.数据显示直观.CUI程序中数据只能以文本的形式线性显示,GUI程序则允许数据以文本.列表.图形等多种形式立体显示. 用户体验在GUI程 ...
- WPF学习之X名称空间详解
X名称空间里面的成员(如X:Name,X:Class)都是写给XAML编译器看的.用来引导XAML代码将XAML代码编译为CLR代码. 4.1X名称空间里面到底都有些什么? x名称空间映射的是:htt ...
- 【WPF学习】第五十章 故事板
正如上一章介绍,WPF动画通过一组动画类(Animation类)表示.使用少数几个熟悉设置相关信息,如开始值.结束值以及持续时间.这显然使得它们非常适合于XAML.不是很清晰的时:如何为特定的事件和属 ...
- WPF学习之资源-Resources
WPF学习之资源-Resources WPF学习之资源-Resources WPF通过资源来保存一些可以被重复利用的样式,对象定义以及一些传统的资源如二进制数据,图片等等,而在其支持上也更能体现出这些 ...
最新文章
- CentOS7.5 -- Ansible部署与应用
- MapHack源代码
- ios realm 文件_iOS开发中使用Realm数据库
- Java中HttpClient设置超时时间
- 【并查集】Union Find
- 用开源组件jcaptcha做jsp彩色验证码
- HTML学习笔记——DOCTYPE和DTD,标准模式和兼容模式
- 数据分析之Pandas(一) 学习资料汇总
- R语言实现PVAR(面板向量自回归模型)
- 远控王 v387 免费
- Linux进程管理软件supervisord使用心得
- PHP的数据类型主要有三大类八小类。
- 写好英语科技论文的诀窍: 主动迎合读者期望,预先回答专家可能质疑--周耀旗教授...
- 火影忍者新忍出击服务器正在维修,火影忍者手游更新公告 新忍出击资源翻倍...
- 手把手教你搭建免流服务器(只限于联通)
- 合并代码时,处理Merge branch ‘dev‘ of ssh: xxxxxx问题
- adb 查看手机的ip地址
- Ubuntu下实时查看Nvidia显卡显存占用情况
- linux创建用户,添加及修改shell
- eclipse默认指向WebContent目录修改为webRoot 设置说明
热门文章
- linux pmap 进程信息,linux之pmap命令简介
- linux pmap was java,Linux性能测试之pmap命令详解
- No modules name “XXX”究极解决办法,踩了很多坑后亲测可行的解决方案
- 通证经济大局观(三十二):民族意识的觉醒
- 进入大学应该做的第一件事
- 基于微信小程序的心理自测咨询APP设计与实现-计算机毕业设计源码+LW文档
- WPF Datagrid控件
- SpringBoot 多种方式配置错误页面
- 阿里云 对象存储java实现OSS文件上传及获取URL
- 损失函数:逻辑回归损失函数 推导简记