WPF学习:4.类型转换和标记扩展

article/2025/1/18 10:51:29

  在上一章,主要介绍了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个重要方法是CanConvertToCanConvertFromConvertToConvertFrom

  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


http://chatgpt.dhexx.cn/article/3qfUjNJ0.shtml

相关文章

排序--Bubble的优化和性能(算法时间、空间复杂度、稳定性)分析

一、算法基本思想 &#xff08;1&#xff09;基本思想 冒泡排序的基本思想就是&#xff1a;从无序序列头部开始&#xff0c;进行两两比较&#xff0c;根据大小交换位置&#xff0c;直到最后将最大&#xff08;小&#xff09;的数据元素交换到了无序队列的队尾&#xff0c;从而…

Git查看分支创建时间

实际应用中&#xff0c;可能需要准确知道指定分支的创建时间。 代码实例如下&#xff1a; git reflog show --dateiso mastergit reflog show --dateiso #######[Shell] 纯文本查看 复制代码 1 $ git reflog show --dateiso master 代码运行效果截图如下&#xff1a; 可以…

git怎样查看分支关系图

git log --oneline --graph --decorate --all

git中查看全部分支的命令

现在介绍一个超级实用、使用频率极高但几乎所有 Git 教程都不重视的命令 git branch -avv&#xff0c;它用来查看全部分支信息&#xff1a; 上图有三行信息&#xff0c;依次说明: 第一行&#xff0c;开头的星号表示当前所在分支&#xff0c;绿色的 master 是分支名&#xff0c…

git 命令查看分支的创建者是谁

在你的工程目录下 打开终端,输入一下命令即可 git log --oneline master | cut -d " " -f 1 | tail -1 | xargs git log 如上图所示&#xff0c; Author 就是创建者&#xff0c;Date 就是创建日期。“提交项目”这个描述是最初我创建分支的备注

git查看当前分支是基于哪个分支拉取

命令&#xff1a; git reflog show --datelocal | grep 当前分支名举例&#xff1a;比如当前分支为develop&#xff0c;那么命令如下&#xff1a; git reflog show --datelocal | grep develop查询结果如下&#xff1a; 在最后一条记录&#xff0c;可以看到信息为&#xff1…

git如何查看分支

如何查看分支 git branch -vvgit如何切换分支 git checkout branch_name查看远程分支 git branch -a查看本地分支 git branch创建分支 git branch test切换分支到test git checkout test删除本地分支 git branch -d xxxxx查看本地和远程分支 -a 前面带*号的代表你当前工…

git如何查看分支的创建人

背景: 项目初期建立了两个模块的分支,后续多模块开发结束,回看代码整理分支的时候发现以前的分支不记得是否为自己所创,为了不误删别人的分支,此时就需要知道这些分支到底是谁建立的.问题: git如何查看分支的创建人?解决: 我是使用sourceTree进行git管理, 解决这个问题核心的就…

Git查看分支从哪个分支创建的

使用命令 Git查看分支创建时间 git reflog show --dateiso <branch name> 如果是feature分支 git reflog show --dateiso feature/设备小程序 提交多的话&#xff0c;按回车滚动到最后一条 最后一条是创建时间 不过一般我们需要的是远程的&#xff0c;分支名加上or…

Git查看分支的创建人

开发小组人多的时候&#xff0c;仓库里会有跟多分支&#xff0c;需要看下某个分支具体是谁创建的。 命令&#xff1a; git for-each-ref --format%(committerdate) %09 %(authorname) %09 %(refname) | sort -k5n -k2M -k3n -k4n输出如下&#xff1a; 有个缺点是日期中的月份…

如何用git查看分支

1 首先从github&#xff0c;gitblit&#xff0c;gitee上下载的项目文件都有一个隐藏的.git文件&#xff0c;先让这个隐藏文件显示出来。在查看里将隐藏的项目勾上。 2 通过vscode打开 3 现在要查看本地仓库的分支用下面这个命令 git branch 4 现在查看远程仓库的分支是在哪个…

【Git】 常用命令速查

一、 Git 常用命令速查 git branch 查看本地所有分支 git status 查看当前状态 git commit 提交 git branch -a 查看所有的分支 git branch -r 查看远程所有分支 git commit -am "init" 提交并且加注释 git remote add origin git192.168.1.119:ndshow git push o…

Git命令:查看分支、创建分支、合并分支

一、查看分支 查看的git命令如下&#xff1a; git branch 列出本地已经存在的分支&#xff0c;并且当前分支会用*标记 git branch -r 查看远程版本库的分支列表 git branch -a 查看所有分支列表&#xff08;包括本地和远程&#xff0c;remotes/开头的表示远程分支&#xff09;…

css 固定定位失效问题 position: fixed

问题&#xff1a; 今天项目做一个电梯导航&#xff0c;用到position: fixed&#xff08;固定定位&#xff09;&#xff0c;发现有定位效果&#xff0c;但是拖动滚动条会显示(会根据页面卷曲&#xff0c;遮盖) 方案&#xff1a; 找了一下原因&#xff0c;我给定位的父盒子加了…

CSS固定定位[相对浏览器] 相对定位[相对自己] 绝对定位[有relative的元素]

1基础 Fixed&#xff1a;固定定位 是相对于浏览器窗口来定位的 Absolution&#xff1a; 绝对定位&#xff1a;当没有父元素或者父元素没有进行定位的时候&#xff0c;就是固定定位&#xff0c;以浏览器为标的物 元素会脱离文档流&#xff0c;若该元素没有设置宽度&#xff0c;…

css绝对定位、相对定位、固定定位

css 定位 一、css的三种定位属性 1. 相对定位 position: relative; 元素相对于自己原来的位置&#xff0c;进行位移。 特性&#xff1a; ​ 1,不脱离文档流;其他元素不受影响 ​ 2,相对于自己的文档流上下左右定位 ​ 3,层级高于其他元素 ​ 4,使用属性:top bottom left r…

CSS定位布局详解

CSS定位布局详解 1.定位布局概述2.固定定位&#xff1a;fixed3.相对定位&#xff1a;relative4.绝对定位&#xff1a;absolute5.静态定位&#xff1a;static 1.定位布局概述 CSS定位使你可以将一个元素精确地放在页面上指定的地方。联合使用定位和浮动&#xff0c;能够创建多种…

html制作固定的菜单栏,CSS固定定位生成网页顶部导航栏实例

固定定位 position:fixed 固定定位是相对与浏览器窗口来定位, 就算页面滚动, 固定定位元素的位置不会变 固定定位元素脱离了标准文档流, 会雅盖主标准文档流里的元素 固定定位元素不再占用空间 ​ p.one { position: fixed; left: 5px; top: 5px; } ​ p.two { position: fixed…

html固定按钮相对位置,css固定定位和绝对定位的区别是什么?

CSS固定定位和绝对定位的区别是什么&#xff1f;下面本篇文章就来给大家介绍一下固定定位和绝对定位的区别。有一定的参考价值&#xff0c;有需要的朋友可以参考一下&#xff0c;希望对大家有所帮助。 绝对定位 绝对定位即脱离文档流的定位。定位参照物为自己的父级&#xff0c…

CSS固定定位 将模块固定到版心右边

目的&#xff1a;在900*1500的版心右边设置50*150固定不随页面滚动条移动的板块 方法&#xff1a;给板块添加固定定位后先用left:50%将其定位在网页中间&#xff0c;再添加版心一半宽的外边距&#xff0c;从版心的中间移动至版心的右侧 代码如下 ​​​​​​​HTML文件&…