WPF 学习之标记扩展

WPF 学习之标记扩展

前记

毕业后一直在学习和使用WPF进行开发,在此就对自己学习和使用WPF的相关技术和知识做一个总结,与大家分享的同时也是对自己所学的内容进行一个巩固。

关于标记扩展主要是从以下几个方面进行一个总结:

  1.   XAML 值转换器
  2.   标记扩展的概念
  3.   使用标记扩展的好处
  4.   XAML内置标记扩展
  5.   自定义标记扩展
  6.  小结

XAML 制转换器虽然使用WPF进行开发可以不依赖XAML,但是XAML作为一种标记语言对UI树的构造较之编程语言更加简洁明了,并且可以将程序的UI部分和逻辑代码进行分离,因此使用XAML配合编程语言可以在开发过程中起到事半功倍的效果;

   XAML作为一种从XML派生的标记语言与XML具有很多的相似之处,对于XAML语言有对应的解析器将其解析为对应的.NET对象,因此XAML中的元素对应着一个.NET对象,特性(Attribute)对应着对象的一个属性(Property);对于对象的简单属性可以直接以一个特性进行复制,对于复杂些的可以用元素属性进行赋值。

例: <TextBlock  FontFamily="Verdana" FontSize="24" >

  <TextBlock.Foreground>

<LinearGradientBrush StartPoint="0,0" EndPoint="0,1">

                    <GradientStop Color="Red" Offset="0"/>

                    <GradientStop Color="Yellow" Offset="1"/>

                </LinearGradientBrush>

<TextBlock.Foreground>

   </ TextBlock  >

在上例中有通过特性直接给对象的相应属性赋值,也可以通过属性元素进行复制,由于在XML或XAML中特性的对应的值是字符串类型而要将其转换为对应属性的.NET类型需要一个类型转换器,大部分情况下我们能像上面FontFamily="Verdana" Color="Red" 直接以字符串的形式赋值是因为微软的开发工程师在框架中对好多类型已经实现了制转换器的功能;在某些情况下需要自己实现一个制转换器也很简单,实现方式类似于数据绑定中的Convertor;实现一个自定义制转换器的步骤如下

1)        定义一个转换类该类必须继承TypeConverter

2)        在需要进行转换的属性或该属性的类的定义处使用特性TypeConvertorAttribute 进行标记;一般是在类的定义处记性标记,那么在所有其它使用该类型的定义中均可以找到转换类进行转换

                       

重载ConverFrom方法 其返回值即为转换后的值;法

标记扩展的概念

 标记扩展也是对属性进行赋值的一种方式,在XAML中使用一对‘{}’中括号表示,当解析遇到{}时不会直接转换为字符串,而是将其当做一个标记扩展进行处理,通过该标记扩展类型找到其真正的值;使用方式如下:

语法:

        标记扩展使用{标记扩展类 参数}语法

    例:Data="{Binding  Path=LinePathGeometry, Mode=TwoWay}"

  此处使用了一个内置的标记扩展BindingExtension类型特性可以省略Attribute此处BindingExtension也可以简写为Binding两者等价;此处给Data属性赋值是间接地,在这里通过标记扩展语法并且传递了 Path Mode两个参数构造了一个特定的BindingExtension类Data的实际值是通过BindingExtension类通过绑定相关语法和规则(关于数据绑定也是WPF核心概念此处限于篇幅处不详细介绍了)返回;

 

使用标记扩展的好处

通过上面的例子我们可以体会到使用标记扩展可以更加灵活的给属性赋值,从而摆脱硬编码的束缚,使整个程序更加健壮;另一方面通过标记扩展语法可以给标记对象传递特定的参数,构造一个特定的对象比如上例中的Binding对象通过设置绑定源 路径 模式 更新方式等等可以将依赖属性绑定到一个特定的对象从而赋值更加灵活方便;此外标记扩展还支持嵌套使用从而使标记扩展更加灵活,因此了解和使用标记扩展可以极大的提高程序的灵活性和健壮性;

XAML内置标记扩展

在WPF框架中内置了一些标记扩展,而这些标记扩展在平时的开发过程中接触到的频率可以说是非常高的比如数据绑定 静态资源 但WPF框架中内置的标记扩展其实种类很少,下面对其做一个简单的归纳,具体使用方法可以查看MSDN文档(PS 在了解了标记扩展的语法 赋值机制后 再来理解和使用这些标记扩展应该就变得更容易些了);

TemplateBinding  DynamicResource  RelativeSource  等;

自定义标记扩展

某些时候需要自定义标记扩展,要实现自定义标记扩展需要从MarkupExtension

继承,派生类的命名遵循添加Extension后缀的约定。

在派生类中需要重载基类的override object ProvideValue(IServiceProvider serviceProvider)方法;该方法才是使用标记扩展进行赋值的属性实际获取的值;

下面的代码是一个自定义的标记扩展的实现例子:

class SelfDefineExtension:MarkupExtension

    {

        public String Name { get; set; }

        public int Age { get; set; }

        public AverageData Data { get; set; }

 

        public SelfDefineExtension()

        {

        }

 

        public SelfDefineExtension(string Name)

        {

            this.Name = Name;

        }

 

        public override object ProvideValue(IServiceProvider serviceProvider)

        {

            SelfDefineClass selfClass = new SelfDefineClass();

            selfClass.Name = this.Name;

            selfClass.Age = this.Age;

            selfClass.Data = this.Data;

            return selfClass;

        }

    }

}

 

实现自定义标记扩展的基本功能非常简单那就是根据传给标记扩展类的参数构造一个特定的对象在重载方法ProvideValue中返回属性实际值;在ProvideValue方法中有个IServiceProvider参数,在某些情况下该参数十分有用可以通过其获取使用该标记扩展的对象和对应的属性;

  IProvideValueTarget ipvt = (IProvideValueTarget)serviceProvider.GetService(typeof(IProvideValueTarget));//获取目标值服务

                if (ipvt != null)

                {

                    _winTarget = ipvt.TargetObject as Window;//标记扩展绑定

}

上例中就是根据此参数获取了使用了此标记扩展的对象(此处是窗体对象)

 

小结:

以上是本人在学习和使用标记扩展的一点经验总结,按自己的想法以及理解记录下来,相比书上或是MSDN文档以及大牛们的经验总结肯定还有很多没涉及和不深入的地方。以上总结XAML元素 属性赋值以及转换的方式对标记扩展的概念,使用方法 赋值原理 自定义标记扩展等按自己的体会进行了一个总结,肯定有些错误的地方,衷心的希望博友们能够提出,相互交流相互进步,你的建议和鼓励是我最大动力所在。

                                                 2013/10/21

原文地址:https://www.cnblogs.com/sharepublic/p/3381531.html