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时用以下语句访问:
搞定!!怎么?编译通不过?因为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的设计者认为没有必要。
WPF学习笔记一 依赖属性及其数据绑定的更多相关文章
- WPF学习笔记二 依赖属性实现原理及性能分析
在这里讨论依赖属性实现原理,目的只是学习WPF是怎么设计依赖属性的,同时更好的使用依赖属性. 首先我们来思考一个简单的问题:我们希望能验证属性的值是否有效,属性变更时进行自己的处理.回顾一下.net的 ...
- WPF 学习笔记-设置属性使窗口不可改变大小
原文:WPF 学习笔记-设置属性使窗口不可改变大小 调整Windows下的ResizeMode属性: ResizeMode = NoResize Resize属性是控制Windows是否可以改变大小, ...
- WPF学习笔记(一):数据绑定之元素到元素绑定
前言 作为一只菜鸟,之前学了一段时间的WPF,但是没有总结,过了一学期发现好多东西都忘记了,很多东西还是需要记下来,以备后续复习. 数据绑定在事件中应用非常广泛,可以有效地减少代码量,那么什么是数据绑 ...
- WPF学习笔记:(二)数据绑定模式与INotifyPropertyChanged接口
数据绑定模式共有四种:OneTime.OneWay.OneWayToSource和TwoWay,默认是TwoWay.一般来说,完成数据绑定要有三个要点:目标属性是依赖属性.绑定设置和实现了INotif ...
- WPF学习笔记:(一)数据绑定与DataContext
前一段半心半意地学习了一下WPF,是从控件入手的,发现巨容易,甚至有些无趣.昨天面试,被问到了很多WPF的特性的东西,直接就傻了.于是乎,还是要去深刻的学习一下WPF.刚刚试了一下数据绑定,几次都没有 ...
- 【WPF学习笔记】之依赖属性
概述: Windows Presentation Foundation (WPF) 提供了一组服务,这些服务可用于扩展公共语言运行时 (CLR) 属性的功能.这些服务通常统称为 WPF 属性系统.由 ...
- WPF 学习笔记-在WPF下创建托盘图标
原文:WPF 学习笔记-在WPF下创建托盘图标 首先需要在项目中引用System.Windows.Forms,System.Drawing; using System; using System.Co ...
- Spring学习笔记之依赖的注解(2)
Spring学习笔记之依赖的注解(2) 1.0 注解,不能单独存在,是Java中的一种类型 1.1 写注解 1.2 注解反射 2.0 spring的注解 spring的 @Controller@Com ...
- SpringMVC:学习笔记(11)——依赖注入与@Autowired
SpringMVC:学习笔记(11)——依赖注入与@Autowired 使用@Autowired 从Spring2.5开始,它引入了一种全新的依赖注入方式,即通过@Autowired注解.这个注解允许 ...
随机推荐
- ES6新增语法(四)——面向对象
ES6中json的2个变化 简写:名字和值相同时,json可以可以简写 let a=12,b=5; let json = { a, b } console.log(json) // { a:12 , ...
- java网络编程基础——网络基础
java网络编程 网络编程基础 1.常用的网络拓扑结构: 星型网络.总线网络.环线网络.树形网络.星型环线网络 2.通信协议的组成 通信协议通常由3部分组成: 语义部分:用于决定通信双方对话类型 语法 ...
- web自动化测试(2):选择selenium优势?与PhantomJS/QTP/Monkey对比
上篇 <web自动化测试(1):再谈UI发展史与UI.功能自动化测试>,自动化测试工具众多, PC端常用的功能自动化测试工具 Selenium:开源工具集,用于回归功能测试或者系统用例说明 ...
- 【Mysql】InnoDB 中的 B+ 树索引
接上一篇内容,InnoDB 的作者想到一种更灵活的方式来管理所有目录项,是什么? 一.目录项记录页 其实这些用户目录项与用户记录很像,只是目录项中的两个列记录的是主键和页号而已,那么就可以复用之前存储 ...
- 分布式ID生成器(CosId)的设计与实现
分布式ID生成器(CosId)设计与实现 CosId 简介 CosId 旨在提供通用.灵活.高性能的分布式 ID 生成器. 目前提供了俩类 ID 生成器: SnowflakeId : 单机 TPS 性 ...
- P4774-屠龙勇士-扩展中国剩余定理
屠龙勇士 很久很久以前,巨龙突然出现,带来了灾难带走公主又消失不见.王国十分危险,世间谁最勇敢,一位英雄出现-- 学习于该大佬博客 那么你就是这位英雄,不过不同的是,你面对的是一群巨龙,虽然巨龙都不会 ...
- 记一次Vue跨导航栏问题解决方案
简述 这篇文章是我项目中,遇到的一个issue,我将解决过程和方法记录下来. 本篇文章基于Vue.js进行的前端页面构建,由于仅涉及前端,将不做数据来源及其他部分的叙述.使用的CSS框架是 Boots ...
- 七个对我最重要的职业建议)--转载来自ruanyifeng博客
原文:http://www.ruanyifeng.com/blog/2015/09/career-advice.html 一.不要别人点什么,就做什么 我的第一份工作,只干了8个月,那家公司就倒闭了. ...
- rsync(873)未授权访问
cd vulhub-master/rsync/common docker -composeup -d 检测 1.列出目标服务器的同步目录 rsync 192.168.244.129:: 2.查看模块文 ...
- 利用 cgroup 的 cpuset 控制器限制进程的 CPU 使用
最近在做一些性能测试的事情,首要前提是控制住 CPU 的使用量.最直观的方法无疑是安装 Docker,在每个配置了参数的容器里运行基准程序. 对于计算密集型任务,在只限制 CPU 的需求下,直接用 L ...