wpf中xaml的类型转换器与标记扩展
2009-02-02 14:05
260 查看
这篇来讲wpf控件属性的类型转换器
类型转换器在asp.net控件中已经有使用过了,由于wpf的界面是可以由xaml组成的,所以标签的便利也需要类型转换器.两者的应用是非常之相似的.
如设置Margin属性
用xaml方式<Button Margin="1,2,3,4"></Button>
cs代码Button btn = new Button();
btn.Margin = new Thickness(1, 2, 3, 4);
通过xaml设置Margin会将此属性通过类型转换器转成Thickness类型.关于类型转换器相关知识,这里不多介绍.下面来介绍xaml的标记扩展功能.
数据绑定语法 {Binding Path=…}
静态资源引用 {StaticResource …}
指定数据类型{x:Type prefix:typeNameValue}
…
标记扩展带来很多好处,一般情况下,xaml的属性值都是文本字符串形式通过类型转换器形式转成对象(标签化语言也存在着局限性).标记扩展可以让属性引用某个静态对象的引用,当然这只是其中的一个功能,语法则是以左右大括号以区别({}).
我想大家在刚学wpf或者silverlight的时候,在设置Margin属性的时候,都常常会忘掉四边的顺序,即左上右下,如下blend的属性编辑器.
![](http://images.cnblogs.com/cnblogs_com/Clingingboy/WindowsLiveWriter/wpf2_DF2F/image_thumb.png)
换个思路,你想把Margin的左上右下的顺序变化就不可以了,因为这是类型转换器,这个顺序是定死的.如果用标记扩展的话,我们可以假设有下面的语法
{Margin Top=76,Left=76,Right=168,Bottom=0}
虽然感觉起来比直接写xx,xx,xx,xx这样麻烦,但增加了灵活性.主要问题是标记扩展可以记录属性值,类型转换器只能用文本字符串表示.
一个复杂属性在xaml的表示方法两种方法都可以,标记扩展提供了一个多的选择.看应用而定.当然在没有类型转换器的情况下,xaml也允许这样写法.相对而言就稍微的复杂一些,一切都是为了简化.<Button>
<Button.Margin>
<Thickness Left="0" Top="0" Right="0" Bottom="0"></Thickness>
</Button.Margin>
</Button>
<Button Margin="{Margin Top=0,Left=0,Right=0,Bottom=0}" />
比较上面三种方式,肯定最后一个最简单,对于记忆不好的也可以尝试第二种,其实第标记扩展也需要你记对象的属性,万一大小写出错那也麻烦,第一种嘛,代码量又太多了,要是都设置一个属性都这样,那代码就多了.所以各有各自的好处.
下面介绍自定义标记扩展的方法
(1)定义一个派生自System.Windows.Markup.MarkupExtension的类,该类要求重写ProvideValue方法
namespace WPF.Controls
{
public class ThicknessExtension : MarkupExtension
{
public override object ProvideValue(IServiceProvider serviceProvider)
{
throw new NotImplementedException();
}
}
}
(2)与xml命名空间关联,在程序集项目中的AssemblyInfo添加元数据,XmlnsDefinition元数据可以帮助统一命名空间,因为这样我们才可以很简单的使用wpf内置控件(很多控件都在不同命名空间下),XmlnsPrefix的作用就如asp.net内置控件以asp开始一样<asp:Label />[assembly: XmlnsDefinition("http://wpf.controls", "WPF.Controls")]
[assembly: XmlnsPrefix("http://wpf.controls", "ext")]现在我们将ProvideValue方法变更为
然后在xaml中使用该扩展标记<Window x:Class="WpfApplication1.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ext="http://wpf.controls"
Title="Window1" Height="100" Width="200">
<Grid>
<Button Margin="{ext:Thickness}" Content="Hello" />
</Grid>
</Window>
上面代码可以成功运行,我们还需要为扩展标记添加属性,用于传递参数.
(3)添加属性. 在xaml中添加的对象,都以默认的构造函数进来,同时可以用MarkupExtensionReturnType指定标记扩展返回的安全类型
[MarkupExtensionReturnType(typeof(Thickness))]
public class ThicknessExtension : MarkupExtension
{
public override object ProvideValue(IServiceProvider serviceProvider)
{
return new Thickness(Left,Top,Right,Bottom);
}
public ThicknessExtension()
{
}
public double Bottom { get; set; }
public double Left { get; set; }
public double Right { get; set; }
public double Top { get; set; }
}
现在就可以使用了<Button x:Name="demo" Margin="{ext:Thickness Left=10,Bottom=10,Right=10,Top=30}"
Content="Hello">
</Button>
类型转换器
类型转换器在asp.net控件中已经有使用过了,由于wpf的界面是可以由xaml组成的,所以标签的便利也需要类型转换器.两者的应用是非常之相似的.
如设置Margin属性
用xaml方式<Button Margin="1,2,3,4"></Button>
cs代码Button btn = new Button();
btn.Margin = new Thickness(1, 2, 3, 4);
通过xaml设置Margin会将此属性通过类型转换器转成Thickness类型.关于类型转换器相关知识,这里不多介绍.下面来介绍xaml的标记扩展功能.
标记扩展
标记扩展在wpf的应用中非常之广泛的.如数据绑定语法 {Binding Path=…}
静态资源引用 {StaticResource …}
指定数据类型{x:Type prefix:typeNameValue}
…
标记扩展带来很多好处,一般情况下,xaml的属性值都是文本字符串形式通过类型转换器形式转成对象(标签化语言也存在着局限性).标记扩展可以让属性引用某个静态对象的引用,当然这只是其中的一个功能,语法则是以左右大括号以区别({}).
左上右下问题
这里我们来比较类型转换器做不到的问题我想大家在刚学wpf或者silverlight的时候,在设置Margin属性的时候,都常常会忘掉四边的顺序,即左上右下,如下blend的属性编辑器.
![](http://images.cnblogs.com/cnblogs_com/Clingingboy/WindowsLiveWriter/wpf2_DF2F/image_thumb.png)
换个思路,你想把Margin的左上右下的顺序变化就不可以了,因为这是类型转换器,这个顺序是定死的.如果用标记扩展的话,我们可以假设有下面的语法
{Margin Top=76,Left=76,Right=168,Bottom=0}
虽然感觉起来比直接写xx,xx,xx,xx这样麻烦,但增加了灵活性.主要问题是标记扩展可以记录属性值,类型转换器只能用文本字符串表示.
一个复杂属性在xaml的表示方法两种方法都可以,标记扩展提供了一个多的选择.看应用而定.当然在没有类型转换器的情况下,xaml也允许这样写法.相对而言就稍微的复杂一些,一切都是为了简化.<Button>
<Button.Margin>
<Thickness Left="0" Top="0" Right="0" Bottom="0"></Thickness>
</Button.Margin>
</Button>
<Button Margin="{Margin Top=0,Left=0,Right=0,Bottom=0}" />
<Button Margin="0,0,0,0" />
比较上面三种方式,肯定最后一个最简单,对于记忆不好的也可以尝试第二种,其实第标记扩展也需要你记对象的属性,万一大小写出错那也麻烦,第一种嘛,代码量又太多了,要是都设置一个属性都这样,那代码就多了.所以各有各自的好处.
自定义标记扩展
标记扩展本身与设计时没有关系,但类型转换器却是设计时必须的功能,二两者又有着类似之处,所以这里介绍一下.下面介绍自定义标记扩展的方法
(1)定义一个派生自System.Windows.Markup.MarkupExtension的类,该类要求重写ProvideValue方法
namespace WPF.Controls
{
public class ThicknessExtension : MarkupExtension
{
public override object ProvideValue(IServiceProvider serviceProvider)
{
throw new NotImplementedException();
}
}
}
(2)与xml命名空间关联,在程序集项目中的AssemblyInfo添加元数据,XmlnsDefinition元数据可以帮助统一命名空间,因为这样我们才可以很简单的使用wpf内置控件(很多控件都在不同命名空间下),XmlnsPrefix的作用就如asp.net内置控件以asp开始一样<asp:Label />[assembly: XmlnsDefinition("http://wpf.controls", "WPF.Controls")]
[assembly: XmlnsPrefix("http://wpf.controls", "ext")]现在我们将ProvideValue方法变更为
public override object ProvideValue(IServiceProvider serviceProvider) { return new Thickness(); }
然后在xaml中使用该扩展标记<Window x:Class="WpfApplication1.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ext="http://wpf.controls"
Title="Window1" Height="100" Width="200">
<Grid>
<Button Margin="{ext:Thickness}" Content="Hello" />
</Grid>
</Window>
上面代码可以成功运行,我们还需要为扩展标记添加属性,用于传递参数.
(3)添加属性. 在xaml中添加的对象,都以默认的构造函数进来,同时可以用MarkupExtensionReturnType指定标记扩展返回的安全类型
[MarkupExtensionReturnType(typeof(Thickness))]
public class ThicknessExtension : MarkupExtension
{
public override object ProvideValue(IServiceProvider serviceProvider)
{
return new Thickness(Left,Top,Right,Bottom);
}
public ThicknessExtension()
{
}
public double Bottom { get; set; }
public double Left { get; set; }
public double Right { get; set; }
public double Top { get; set; }
}
现在就可以使用了<Button x:Name="demo" Margin="{ext:Thickness Left=10,Bottom=10,Right=10,Top=30}"
Content="Hello">
</Button>
相关文章推荐
- wpf中xaml的类型转换器与标记扩展
- WPF学习:4.类型转换和标记扩展
- 闲话WPF之五(XAML中的类型转换)
- WPF 之 XAML语法,对象属性赋值(简单赋值、TypeConverter 标签属性与对象属性映射、标记扩展),引用外部库
- WPF Summary:XAML标记扩展
- WPF中在XAML中实现数据类型转换的两种方法
- wpf 扩展标记应用 数据类型转
- 稳扎稳打Silverlight(66) - 5.0其它之自定义 XAML 扩展标记, 通过 XNA 处理声音效果, 支持矢量打印, 统计连击的次数
- WPF:实现自定义标记扩展
- XAML实例教程系列 - 标记扩展(Markup Extensions) 六
- WPF学习系列012: 2.7.4 XAML 扩展部分
- ASP.NETC#通用扩展函数之TypeParse 类型转换方便多了
- 6.Swift协议|扩展|访问权限|异常调试|类型转换|运算函数|ARC|类类型初试化器|值类型初始化器
- Swift:(十二)、类型转换、嵌套类型、扩展
- 关于类型转换时的“符号扩展”
- WPF第一章(XAML前台标记语言(Chapter02代码讲解))
- C++/clr 本地自定义类型和托管自定义类型的相互转换 【MSDN如何:扩展封送处理库】
- WPF值通用的类型转换器详解(转)
- WPF数据类型转换
- WPF,Silverlight与XAML读书笔记(3) - 标记扩展