《深入浅出WPF》笔记三

1、Field:字段,封装在类中的变量。
Method:方法,封装在类中的函数。
成员:类中的字段和方法,可分为静态成员和非静态成员。
静态字段在内存中只有一份拷贝。
非静态字段是每个实例拥有一个拷贝。
方法无论是否静态,在内存中都只有一份拷贝。
2、CLR属性
直接把字段的数据暴露给外界的作法很不安全,我们希望对象自己有能力判断将要写入的字段值是否正确。于是提供了Set和Get方法来对private的字段进行读取,这就是private字段的安全包装。.Net Framework将Get/Set方法合并成了属性(Property),也称为CLR属性。
属性的编译结果实际上是两个方法(Get/Set),在内存中只有一份拷贝,不会增加内存负担。
3、依赖属性
一种可以自己没有值,并能通过Binding从数据源获得值得属性。
4、依赖对象(Dependency Object)
对象在被创建时并不包含用于存储数据的空间,只保留在需要用到数据时能够获得默认值、借用其他对象数据、或实时分配空间的能力,这种能力依靠依赖属性(Dependency Property)来实现。
WPF中所有UI控件都是依赖对象。
5、依赖属性的包装器(wrapper)是一个CLR属性。包装器以“实例属性”的形式向外界暴露依赖属性,这样一个依赖 属性才能成为数据源的Path。
6、自定义一个依赖对象并声明一个依赖属性。

 1 public class Student:DependencyObject
 2 {
 3     public Student()
 4     {
 5
 6     }
 7
 8     public static readonly DependencyProperty NameProperty=
 9             DependencyProperty.Register("Name",typeof(string),typeof(Student));
10 }

7、直接使用上面的依赖属性。通过依赖对象的GetValue和SetValue方法对依赖属性的值进行读写。

1 Student stu=new Student();
2 stu.SetValue(Student.NameProperty,this.textBox1.Text);
3 this.textBox2.Text=(string)stu.GetValue(Student.NameProperty);

8、直接使用GetValue和SetValue方法略不方便,因此大多数情况下我们会为依赖属性添加一个CLR属性外包装。有了这个包装,依赖对象就有了用于暴露数据的Binding Path。

1 public string Name
2 {
3     get{return (string)GetValue(NameProperty);}
4     set{SetValue(NameProperty,value);}
5 }

依赖属性自带NorifyPropertyChanged的功能。
9、声明依赖属性的snippet:输入propdp,连续按两次Tab键,就出现了标准依赖属性的代码段。
10、依赖属性的创建和注册过程:
创建一个依赖DependencyProperty实例,用它的CLR属性名和宿主类型名生成HashCode,最后把HashCode和DependencyProperty实例作为Key-Value对存到全局的名为PropertyFromName的HashCode中。最后,生成的DependencyProperty实例作为返回值返回。
每个DependencyProperty实例都有一个唯一的GlobalIndex的int类型属性,这个值才是DependencyProperty实例的哈希值,通过这个值可以直接检索到该实例。
11、依赖属性如何存储值
每个DependencyObject实例都自带一个EffectiveValueEntry类型数组,而每个EffectiveValueEntry的PropertyIndex属性的值就是DependencyProperty实例的GlobalIndex。
当某个依赖属性的值要被读取时,算法会从EffectiveValueEntry[]数组中检索值,如果没有值,就会返回依赖属性的默认值。
被static readonly关键字修饰的依赖属性对象的作用是用来检索真正的属性值而不是存储值。
12、附加属性
snippet:propa
声明一个附加属性:

 1     class School:DependencyObject
 2     {
 3
 4         public static int GetGrade(DependencyObject obj)
 5         {
 6             return (int)obj.GetValue(GradeProperty);
 7         }
 8
 9         public static void SetGrade(DependencyObject obj, int value)
10         {
11             obj.SetValue(GradeProperty, value);
12         }
13
14         // Using a DependencyProperty as the backing store for Grade.  This enables animation, styling, binding, etc...
15         public static readonly DependencyProperty GradeProperty =
16             DependencyProperty.RegisterAttached("Grade", typeof(int), typeof(ownerclass), new PropertyMetadata(0));
17
18     }

使用附加属性:

1 Student stu = new Student();
2 School.SetGrade(stu, 6);
3 int grade = School.GetGrade(stu);

附加属性的本质是依赖属性,也可以使用Binding依赖在其他对象的数据上。
13、路由事件(RoutedEvent)
与依赖属性类似,每个路由事件都有一个自己的CLR事件。
监听和处理路由事件的方法:
C#:

this.grid.AddHandler(Button.ClickEvent,new RoutedEventHandler(this.ButtonClicked));

XAML:

<Grid x:Name="gridRoot" Button.Click="ButtonClicked">
</Grid>

14、RoutedEventArgs的两个属性
Source:LogicalTree上的消息源头
OriginalSource:VisualTree上的消息源头
15、附加事件
附加事件的宿主没有可视化实体的界面元素。比如,设计一个Student类,当Student实例的属性值发生变化时就激发一个路由事件。为了发送路由事件,可以借用Button等UI元素的RaiseEvent()方法。
定义附加事件:

 1     class Student
 2     {
 3         public static readonly RoutedEvent NameChangedEvent = EventManager.RegisterRoutedEvent
 4             ("NameChanged",RoutingStrategy.Bubble,typeof(RoutedEventHandler),typeof(Student));
 5
 6         public static void AddNameChangedHandler(DependencyObject d, RoutedEventHandler h)
 7         {
 8             UIElement e = d as UIElement;
 9             if (e != null)
10             {
11                 e.AddHandler(Student.NameChangedEvent, h);
12             }
13         }
14
15         public static void RemoveNameChangedHandler(DependencyObject d, RoutedEventHandler h)
16         {
17             UIElement e = d as UIElement;
18             if (e != null)
19             {
20                 e.RemoveHandler(Student.NameChangedEvent, h);
21             }
22         }
23         public int Id { get; set; }
24         public string Name { get; set; }
25     }

16、附加事件的路由第一站是激发它的元素(如上例中的button)
17、实际上,附加事件一般都是定义在像Binding、Mouse、KeyBoard等全局的Helper类中。
18、路由命令(RoutedCommand)
使用命令可以避免自己写代码去判断Button是否可用以及添加快捷键。
命令目标发送路由事件CanExecute和Executed等,这些路由事件沿着UI元素树向上传递并被CommandBinding捕捉。

时间: 2024-10-29 16:58:01

《深入浅出WPF》笔记三的相关文章

javascript高级程序设计——笔记

javascript高级程序设计--笔记 基本概念 基本数据类型包括Undefined/Null/Boolean/Number和String 无须指定函数的返回值,实际上,未指定返回值的函数返回的是一个特殊的undefined值 变量.作用域和内存问题 基本类型值在内存中占据固定大小的空间,因此保存在栈内存中 引用类型的值是对象,保存在堆内存中 确定一个值是哪种基本类型用typeof,确定一个值是哪种引用用instanceof 所有变量都存在于一个执行环境当中,这个执行环境决定了变量的生命周期,

Javascript高级程序设计——第三章:基本概念

javascript高级程序设计——第三章:基本概念 一.语法 EMCA-262通过叫做ECMAScript的“伪语言”为我们描述了javascript实现的基本概念 javascript借鉴了C的语法,区分大小写,标示符以字母.下划线.或美元符号($)开头,注释可以用 // 或者/* */ 严格模式: ECMAScript 5引入了严格模式,在严格模式下不确定的行为将得到处理,通过在顶部添加 “use strict”来启用严格模式: function fuc(){ "use strict&qu

JavaScript高级程序设计学习(三)之变量、作用域和内存问题

这次讲的主要是变量,作用域和内存问题. 任何一门编程语言,都涉及这三个. 变量,比如全局变量,局部变量等,作用域,也分全局作用域和方法作用域,内存问题,在java中就涉及到一个垃圾回收的问题,由于java中涉及到jvm,因此可以自动垃圾回收和内存分配,而不需要手动. 一.变量 每个变量都有其类型,数据类型.在java中分基本数据类型和引用数据类型,js同样如此. 面试题:java的基本数据类型有哪些,及其所占字节?引用类型有哪些? java基本数据类型分别为int(4),float(4),dou

javascript高级程序设计笔记1

最近在看javascript高级程序设计,看之前觉得自己的js学得还不错,然后,看了没几页就觉得自己好像没有学过一样,这主要写写我以前不完全了解的一些知识. 首先是关于基本数据类型的,从Number开始,以前经常用parseInt来转换数值,看过书才知道,这个函数的本意是专门用于把字符串转换成数值,而且以前也不知道它具体是怎么一个转换规则.先来看看Number()函数的转换规则: 1.如果是Boolean 值,true 和false 将分别被转换为1 和0.2.如果是数字值,只是简单的传入和返回

《JavaScript高级程序设计 第三版》 前2章 Javascript简介与HTML 读书笔记

第一章:Javascript简介 1.JavaScript诞生于1995年,当时,它的主要目的是处理以前由服务器端语言(如Perl)负责的一些输入验证操作.现在,JavaScript是一种专为与网页交互而设计的脚本语言. 注:Netscape(网景)公司研发,Java是sun公司研发,原名为LiveScript,为了搭上媒体热炒的Java的顺风车,更名为JavaScript 2.微软推出JSript的和网景的JavaScript相竞争,最后微软胜利.ECMA指定了规定并重新命名为ECMAScri

【javascript高级程序设计笔记】第一章与第三章

第1章 javascript简介 1.2Javascript实现 一个完整的javascript实现由下列三个不同的部分组成 核心(ECMAScript) 提供核心语言功能 文档对象模型(DOM) 提供访问和操作网页内容的方法和接口 浏览器对象模型(BOM)提供与浏览器交互的方法和接口 ECMAScript 它规定了这门语言的下列组成部分: 语法  类型  语句  关键字 保留字 操作符 对象 ECMA-262第5版,发布于2009年. 文档对象模型(DOM) Document Object M

javascript高级程序设计--笔记01

概述 JavaScript的实现包含三个部分: 1  核心(ECMAScript)   提供核心语言功能 2  文档对象模型(DOM)  一套提供了访问以及操作网页内容的API 3  浏览器对象模型(BOM)  一套提供了与浏览器交互的API ECMAScript仅仅定义了这门语言的基础,如定义了:语法.类型.语句.关键字等,实际上这门语言本身不包含输入输出定义. 而现实中,ECMAScript大多借用了某些宿主环境(如web浏览器,Node,Adobe Flash)来实现丰富的功能,这些宿主环

javascript高级程序设计第三版 读书笔记

第三章   基本概念 1.在JavaScript中是区分大小写的,第一个字符是字母 _ 或者$,其他字符可以试数字 字母 _ 或者$,命名格式要求是驼峰式书写(第一个字母小写,剩下的每个有意义的单词开头大写  比如fontSize) 2.单行注释//  块级注释为/*多行 内容*/ 不得使用关键字和保留字 3.在JavaScript中变量是松散型的   可以为任何一种类型 4.用var操作符定义的变量成为定义该变量的作用域中的局部变量. function test(){ var i = 'hi'

javascript高级程序设计第三版dom元素大小笔记

是滚动大小(scroll dimension),指的是包含滚动内容的元素的大小.有些元素(例如 <html>元素),即使没有执行任何代码也能自动地添加滚动条:但另外一些元素,则需要通过 CSS 的 overflow 属性进行设置才能滚动.以下是 4 个与滚动大小相关的属性. 在IE8以下scrollHeight=元素内容本身的高度. 1.增加边框,不同浏览器有不同解释. 谷歌火狐IE>=8会忽略边框的大小. 2,增加内边距,最终值是width||height+padding ie8以下是

javascript高级程序设计笔记(第5章 引用类型)

1.Object类型 两种方式定义:对象字面量.new 两种方式访问:括号.点 2.Array类型 2.1  定义方式:new Array.数组字面量 2.2  lenght属性:可以利用它方便的想数组末尾添加元素 2.3  检测数组 instanceof isArray()方法  2.4  toString().soLocaleString().valueOf().join()方法 2.5.栈方法   push()方法:逐个添加到数组末尾,并返回修改后的数组长度 pop()方法:返回数组的最后