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:\images\ButtonPressed.png",否则显示图片"c:\images\ButtonNormal.png".   xaml代码

 
  
< Button.Template >
< ControlTemplate TargetType = " {x:Type Button} " >
< Grid >
< Image x:Name = " imgNormal "
Source
= " c:\images\ButtonNormal.png " Visibility = " Visible " />
< Image x:Name = " imgPressed "
Source
= " c:\images\ButtonPressed.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:\images\ButtonNormal.png"  
 PressedImage ="c:\images\ButtonPressed.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的设计者认为没有必要。

转载于:https://www.cnblogs.com/zhongxg/archive/2011/05/25/2056530.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值