• WPF学习笔记一 依赖属性及其数据绑定


    本文想通过由浅入深的讲解让读者比较深的理解依赖属性.  首先,我们回顾一下依赖属性的发展历史.

      最初,人们提出面向对象编程时,并没有属性这个说法,当时叫做成员变量.一个对象由成员变量和成员函数组成,如下:

    Public Class A{
    Public int Index;//成员变量
    Public void Fun(){} //成员函数
    } 

    后来,提出了对成员变量的改进,增加了get/set 方法,成员变量自然也叫属性了。.net采用了这种方法:

    Public Class A{
          Private int index;//属性
       Public  int Index{
            Set{index = Value;}
            Get{return index ;}
         }
       Public void Fun(){} //方法
    }

    到了WPF, 终于变成依赖属性(WPF大部分属性都是依赖属性)。我们先看一个依赖属性的实现,再理解。

    public partial class MyButton : Button {
           public static DependencyProperty PressedImageProperty;//依赖属性
     
           public string PressedImage {
               get { return (string)GetValue(PressedImageProperty); }
               set { SetValue(PressedImageProperty, value); }
           }
     
           static MyButton() {
               PressedImageProperty = DependencyProperty.Register(
                   "PressedImage", typeof(string), typeof(MyButton),
                   new FrameworkPropertyMetadata(""));
           }
     
           public MyButton () {
               InitializeComponent();
           }

    上面实现了一个PressedImage的依赖属性。和.net属性比较有几点区别:

     1。依赖属性的实体是静态的,类型为DependencyProperty。

       如上例中的属性PressedImage,如果在.net中会这样定义它的实体

        public string pressedImage;

        依赖属性却是这样:

         public static DependencyProperty PressedImageProperty;

      2。多了一个Register。

      3. 它的Get/Set方法借助DependencyObject的GetValue/SetValue来实现.

    但凭这些区别是没法理解依赖属性,因为你不知道DependencyProperty,DependencyObject怎么实现的.这里我只能说一下依赖属性一个特点:

       在面向对象编程时,一个对象有自己的各种属性,我们以往创建一个对象时,它的属性值就保存在对象本身.但依赖属性却不是把属性值保存在对象本身,而是保存在一张公共的依赖属性表里,它包含所有对象的依赖属性.因此,当我们要知道一个对象的某个属性时,WPF不是从该对象直接取出,而是从那张公共的依赖属性表里取出.

     呵呵,大概你明白了为什么依赖属性会变得复杂起来.实际上,功能也强大得多.

     下面就来讨论自定义依赖属性和它的数据绑定.

    通过例子说明。对上文MyButton进行修进,实现以下功能:当MyButton被按下时显示图片"c:imagesButtonPressed.png",否则显示图片"c:imagesButtonNormal.png".   xaml代码

    复制代码
    <Button.Template>
    <ControlTemplate TargetType="{x:Type Button}">
    <Grid>
    <Image x:Name="imgNormal"
    Source="c:imagesButtonNormal.png" Visibility="Visible"/>
    <Image x:Name="imgPressed"
    Source="c:imagesButtonPressed.png" Visibility="Hidden" />
    </Grid>
    <ControlTemplate.Triggers>
    <Trigger Property="IsPressed" Value="True">
    <Setter TargetName="imgNormal" Property="Visibility" Value="Hidden"/>
    <Setter TargetName="imgPressed" Property="Visibility" Value="Visible"/>
    </Trigger>
    </ControlTemplate.Triggers>
    </ControlTemplate>
    </Button.Template>
    复制代码

      cs文件代码:

    public partial class MyButton : Button {
          
           public MyButton () {
               InitializeComponent();
           }

    上面的代码看不懂也没关系,并没有用到依赖属性。 但同时,这个MyButton并没有使用价值,因为他的图片是固定的。我们希望MyButton的图片可以由用户来设定。在上面的xaml文件中,只需改变Image的Source属性。WPF的方法就是数据绑定,也就是把Image的Source属性绑定到一个变量,修改一下xaml:

    复制代码
    <Button.Template>
    <ControlTemplate TargetType="{x:Type Button}">
         <Grid>      
    <Image x:Name="imgNormal" Source="{Binding Path=NormalImage}" Visibility="Visible"/>
         <Image x:Name="imgPressed" Source="{Binding Path=PressedImage}" Visibility="Hidden" />
         </Grid>    
    <ControlTemplate.Triggers>      
    <Trigger Property="IsPressed" Value="True">
              <Setter TargetName="imgNormal" Property="Visibility" Value="Hidden"/>
              <Setter TargetName="imgPressed" Property="Visibility" Value="Visible"/>
           </Trigger>    
    </ControlTemplate.Triggers>  
    </ControlTemplate>
    </Button.Template>
    复制代码

    imgNormal的图片路径绑定变量NormalImage, imgPressed的图片路径绑定到PressedImage,再在MyButton类中增加2个属性NormalImage,PressedImage

     public partial class MyButton : Button {
               public   string NormalImage;
               public   string NormalImage;
                public MyButton () {
                InitializeComponent();
           }
    

     在使用MyButton时用以下语句访问:

    <my:MyButton NormalImage="c:imagesButtonNormal.png" 
     PressedImage="c:imagesButtonPressed.png" />

       搞定!!怎么?编译通不过?因为NormalImage和PressedImage不是依赖属性,所以编译无法通过。 那就继续改吧,把NormalImage和PressedImage改成依赖属性。

    MyButton.cs的最后代码如下: 

    public partial class MyButton : Button {
           public static DependencyProperty NormalImageProperty;
           public static DependencyProperty PressedImageProperty;
     
           public string NormalImage {
               get { return (string)GetValue(NormalImageProperty); }
               set { SetValue(NormalImageProperty, value); }
           }
     
           public string PressedImage {
               get { return (string)GetValue(PressedImageProperty); }
               set { SetValue(PressedImageProperty, value); }
           }
     
           static MyButton () {
               NormalImageProperty = DependencyProperty.Register(
                   "NormalImage", typeof(string), typeof(MyButton ),
                   new FrameworkPropertyMetadata(""));
     
               PressedImageProperty = DependencyProperty.Register(
                   "PressedImage", typeof(string), typeof(MyButton ),
                   new FrameworkPropertyMetadata(""));
           }
     
           public MyButton () {
               InitializeComponent();
           }

    为什么xaml不支持普通属性?

    回顾一下WPF的基本理念:真正做到了分离界面设计人员与开发人员的工作。也就是说,xaml文件呈现的是用户界面,从xaml到用户界面的转化不是由编译器直接编译成用户界面的运行代码(这样和原来的WIN FORM又没有区别了),而是由WPF本身类库来来完成的,打个比方,XAML有如下代码:

    <Button Background="White"></Button>
    

     其中的“White”是如何与C#中的System.Windows.Media.Brushes.White等价的呢?。原来WPF提供了Brush数据类型的转换器。

    对于简单属性(如int类型的), WPF要解释它并不难,如果是自定义类型的呢,WPF要解释它也不难,比如要求开发人员在使用自定义类型的属性时,同时提供该自定义类型的转换器。因此,个人认为,xaml不支持普通属性的原因就是WPF的设计者认为没有必要。

     
     
  • 相关阅读:
    自从学会了搭建开源网站,妈妈再也不担心我找不到web自动化学习环境啦!
    领导要我6点下班前创建1000个有效的手机号,现在5点半了!教你用random模块10分钟搞定!
    python:字符串 扩展分片:第三个限制值
    python字符串:索引和分片
    测试基础:测试用例设计策略
    测试基础:软件测试思维方式
    面试整理:python列表面试习题
    面试整理:linux
    测试的一些思考
    python ConfigParse模块中的方法
  • 原文地址:https://www.cnblogs.com/bruce1992/p/14196808.html
Copyright © 2020-2023  润新知