`
clingingboy
  • 浏览: 25661 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
最近访客 更多访客>>
社区版块
存档分类
最新评论

wpf中xaml的类型转换器与标记扩展

阅读更多

    这篇来讲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的标记扩展功能.

标记扩展


标记扩展在wpf的应用中非常之广泛的.如
数据绑定语法 {Binding Path=…}
静态资源引用 {StaticResource …}
指定数据类型{x:Type prefix:typeNameValue}

标记扩展带来很多好处,一般情况下,xaml的属性值都是文本字符串形式通过类型转换器形式转成对象(标签化语言也存在着局限性).标记扩展可以让属性引用某个静态对象的引用,当然这只是其中的一个功能,语法则是以左右大括号以区别({}).

左上右下问题


这里我们来比较类型转换器做不到的问题

我想大家在刚学wpf或者silverlight的时候,在设置Margin属性的时候,都常常会忘掉四边的顺序,即左上右下,如下blend的属性编辑器.

image

换个思路,你想把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揭秘 第一章 wpf 开发

     2.5 类型转换器   2.6 标记扩展   2.7 对象元素的子元素   2.7.1 内容属性   2.7.2 集合项   2.7.3 更多类型转换   2.8 编译:将XAML与过程式代码混合使用   2.8.1 在运行时加载和解析XAML...

    WPF揭秘 第四章 wpf 开发

     2.5 类型转换器   2.6 标记扩展   2.7 对象元素的子元素   2.7.1 内容属性   2.7.2 集合项   2.7.3 更多类型转换   2.8 编译:将XAML与过程式代码混合使用   2.8.1 在运行时加载和解析XAML...

    wpf完全教程1-4章

     2.5 类型转换器   2.6 标记扩展   2.7 对象元素的子元素   2.7.1 内容属性   2.7.2 集合项   2.7.3 更多类型转换   2.8 编译:将XAML与过程式代码混合使用   2.8.1 在运行时加载和解析XAML...

    wpf编程宝典c#2010版pdf(全)1/3包,共118M

     2.3.1 简单属性与类型转换器  2.3.2 复杂属性  2.3.3 标记扩展  2.3.4 附加属性  2.3.5 嵌套元素  2.3.6 特殊字符与空白  2.3.7 事件  2.3.8 完整的EightBall示例  2.4 使用其他名称空间中的类型  2.5 ...

    wpf编程宝典c#2010版pdf(全)2/3包,共118M

     2.3.1 简单属性与类型转换器  2.3.2 复杂属性  2.3.3 标记扩展  2.3.4 附加属性  2.3.5 嵌套元素  2.3.6 特殊字符与空白  2.3.7 事件  2.3.8 完整的EightBall示例  2.4 使用其他名称空间中的类型  2.5 ...

    WPF揭秘 第二章 wpf 开发

     2.5 类型转换器   2.6 标记扩展   2.7 对象元素的子元素   2.7.1 内容属性   2.7.2 集合项   2.7.3 更多类型转换   2.8 编译:将XAML与过程式代码混合使用   2.8.1 在运行时加载和解析XAML...

    WPF揭秘 第三章 wpf 开发

     2.5 类型转换器   2.6 标记扩展   2.7 对象元素的子元素   2.7.1 内容属性   2.7.2 集合项   2.7.3 更多类型转换   2.8 编译:将XAML与过程式代码混合使用   2.8.1 在运行时加载和解析XAML...

    WPF编程宝典 part2

    2.3.1 简单属性与类型转换器 25 2.3.2 复杂属性 26 2.3.3 标记扩展 28 2.3.4 附加属性 29 2.3.5 嵌套元素 30 2.3.6 特殊字符与空白 32 2.3.7 事件 34 2.3.8 完整的Eight Ball Answer示例 35 2.4 使用其他名称空间中...

    WPF编程宝典 part1

    2.3.1 简单属性与类型转换器 25 2.3.2 复杂属性 26 2.3.3 标记扩展 28 2.3.4 附加属性 29 2.3.5 嵌套元素 30 2.3.6 特殊字符与空白 32 2.3.7 事件 34 2.3.8 完整的Eight Ball Answer示例 35 2.4 使用其他名称空间中...

    一款非常好的WPF编程宝典2010 源代码

    2.3.1 简单属性与类型转换器 27 2.3.2 复杂属性 29 2.3.3 标记扩展 30 2.3.4 附加属性 31 2.3.5 嵌套元素 32 2.3.6 特殊字符与空白字符 35 2.3.7 事件 36 2.3.8 完整的Eight Ball示例程序 38 2.4 使用其他...

    CalcBinding:高级WPF绑定,支持Path属性和其他功能中的表达式

    CalcBinding CalcBinding是高级绑定标记扩展,它使您可以在xaml中编写计算的绑定表达式,而无需自定义转换器。 CalcBinding可以自动将布尔值转换为可见性转换,不同的代数运算,逆表达等。 CalcBinding使绑定表达式...

    Apress.Pro.WPF.in.C.Sharp.2008.2nd.Edition.Feb.2008

    2.3.1 简单属性与类型转换器 27 2.3.2 复杂属性 29 2.3.3 标记扩展 30 2.3.4 附加属性 31 2.3.5 嵌套元素 32 2.3.6 特殊字符与空白字符 35 2.3.7 事件 36 2.3.8 完整的Eight Ball示例程序 38 2.4 使用其他名称空间中...

    MahApps.Metro.IconPacks:一个库中用于WPF和UWP的超赞图标包

    NET Core(3.0和3.1)和UWP 这个IconPacks库包含控件,标记扩展和转换器,可以通过简单的方式使用这些很棒的图标。 图标集版∑ NuGet 在一个包中包含所有图标的完整IconPacks集合1.1.0 1151 2.0.7 15000.0.12 331 ...

Global site tag (gtag.js) - Google Analytics