认识双向绑定在框架中的作用

因为 Vue 是数据双向绑定的框架,而整个框架的由三个部分组成:

  • 数据层(Model):应用的数据及业务逻辑,为开发者编写的业务代码;
  • 视图层(View):应用的展示效果,各类UI组件,由template 和 css 组成的代码;
  • 业务逻辑层(ViewModel):框架封装的核心,它负责将数据与视图关联起来;

而上面的这个分层的架构方案,可以用一个专业术语进行称呼:MVVM。(详细的MVVM知识不在讲解范围内,只需要清楚双向绑定在此架构中作用和位置即可)
这里的控制层的核心功能便是 “数据双向绑定” 。自然,我们只需弄懂它 是什么,便可以进一步了解数据绑定的原理。

理解ViewModel

它的主要职责就是:

  1. 数据变化后更新视图;
  2. 视图变化后更新数据;

那么,就可以得出它主要由两个部分组成:

  1. 监听器(Observer):观察数据,做到时刻清楚数据的任何变化,然后通知视图更新;
  2. 解析器(Compiler):观察UI,做到时刻清楚视图发生的一切交互,然后更新数据;

然后把二者组合起来,一个具有数据双向绑定的框架就诞生了。

双向绑定如何实现的?

实现监听器

确保它是一个独立的功能,它的任务就是监听数据的变化,并提供通知功能。
监听数据变化常见的方式有三种:

  • 观察者模式(发布+订阅);
  • 数据劫持;
  • 脏检查;

第三种,是 AngularJS 最早所提供的监听数据变化方式,而 Vue 是采用前两者的组合,那么让我们来看看它们是怎么被运用的。

观察者模式

观察者模式是一种对象行为模式。它定义对象间的一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
在观察者模式中,主导的是起通知作用的发布者,它发出通知时并不需要知道谁是它的观察者,可以有任意数目的观察者订阅并接收通知
举例代码如下:

/**
 发布者
 */
function Subject() {
  
  // 单个发布者的所有订阅者
  this.observers = [];
  
  // 添加一个订阅者
  this.attach = function(callback) {
    this.observers.push(callback);
  };
  
  // 通过所有的订阅者
  this.notify = function(value) {
    this.observers.forEach(callback => callback(value));
  };
}

/**
 * 订阅者
 */
function Observer(queue, key, callback) {
  queue[key].attach(callback);
}

// ====

// 手动更新数据
function setData(data, key, value) {
    data[key] = value;

    // 通知此值的所有订阅者,数据发生了更新
    messageQueue[key].notify(value);
}

// ====

// 消息队列
const messageQueue = {};

// 数据
const myData = { value: "" };

// 将每个数据属性添加可订阅的入口
for (let key in myData) {
  messageQueue[key] = new Subject();
}

// 订阅 value 值的变化
Observer(messageQueue, "value", value => {
  console.warn("value updated:", value);
});

// 更新数据
setData(myData, "value", "hello world.");
setData(myData, "value", 100);
setData(myData, "value", true);

消息队列(queue)

我们可以看到,单纯的订阅和发布功能,它们彼此是独立存在的,因此还需要一个消息队列来关联他们。
上面的例子中,消息队列是作为一个全局存储变量,而在框架中则是封装起来的,每个 new Vue() 都有独立的一个队列,在下面我们将具体演示。

数据劫持

其实,就数据监听来说,观察者就已经满足了需求。但是,为什么和Vue不一样呢?因为 Vue 进行了优化,添加了数据劫持。
2009 年发布的 ECMAScript 5 中新增了一个 Object.definePropotype 的特性(具体使用不在此文章讲解范围内,请自行了解 developer.mozilla.org/zh-CN/docs/… ),能够定义对象属性的 getter 和 setter ,这可就厉害了,要知道 JavaScript 中一切皆对象。
那么我们的 setData(myData, ‘value’, 100); 就可以替换成 myData.value = 100; 的编写方式。从语法和使用上都变的更简单。
以下是变动后的代码:

// 发布者
function Subject() {
  this.observers = [];
  this.attach = function(callback) {
    this.observers.push(callback);
  };
  this.notify = function(value) {
    this.observers.forEach(callback => callback(value));
  };
}

// 订阅者
function Observer(queue, key, callback) {
  queue[key].attach(callback);
}

// ====

// 数据拦截器
function Watcher(data, queue) {
  for (let key in data) {
    let value = data[key];
    Object.defineProperty(data, key, {
      enumerable: true,
      configurable: true,
      get: () => value,
      set: newValue => {
        value = newValue;

        // 通知此值的所有订阅者,数据发生了更新
        queue[key].notify(value);
      }
    });
  }
  return data;
}

// ====

// 消息队列
const messageQueue = {};

// 数据
const myData = Watcher({ value: "" }, messageQueue);

// 将每个数据属性都添加到观察者的消息队列中
for (let key in myData) {
  messageQueue[key] = new Subject();
}

// 订阅 value 值的变化
Observer(messageQueue, "value", value => {
  console.warn("value updated:", value);
});

// 更新数据
myData.value = "hello world.";
myData.value = 100;
myData.value = true;

当然,ES2015 已经出来有点时间了,所以应尽用新的解决方案 Proxy(具体的使用请自行了解哦 developer.mozilla.org/zh-CN/docs/… ),讲到它主要是因为 Vue3 就采用了此方案。至于性能和具体的差异,之后有机会再单独分享,这里就不细说,让我们看看新的语法怎么写呢?

代码:

// 发布者
function Subject() {
  this.observers = [];
  this.attach = function(callback) {
    this.observers.push(callback);
  };
  this.notify = function(value) {
    this.observers.forEach(callback => callback(value));
  };
}

// 订阅者
function Observer(queue, key, callback) {
  queue[key].attach(callback);
}

// ====

// 数据拦截器 - 代理方式
function ProxyWatcher(data, queue) {
  return new Proxy(data, {
    get: (target, key) => target[key],
    set(target, key, value) {
      target[key] = value;

      // 通知此值的所有订阅者,数据发生了更新
      queue[key].notify(value);
    }
  });
}

// ====

// 消息队列
const messageQueue = {};

// 数据
const myData = ProxyWatcher({ value: "" }, messageQueue);

// 将每个数据属性都添加到观察者的消息队列中
for (let key in myData) {
  messageQueue[key] = new Subject();
}

// 订阅 value 值的变化
Observer(messageQueue, "value", value => {
  console.warn("value updated:", value);
});

// 更新数据
myData.value = "hello world.";
myData.value = 100;
myData.value = true;

以上,我们已经完成双向绑定中的数据层的功能,现在任何的数据变化,我们都可以及时的知道,并关联任何想要做的事情,比如更新视图。

接下来就是模板的操作了,也就是 Compile 模板解析功能。

模板解析(实现视图到数据的绑定)

对于DOM的操作,目前常见的方式有:

  • 原生或者基于库的DOM操作;
  • 将DOM转换为Virtual DOM,然后进行对比与更新;
  • 使用原生的Web Component技术;

以上三种的差异与性能等,之后有机会再单独分享。在Vue中使用的是 Virtual DOM 的方式,因为它比直接操作 DOM 所消耗的性能要少很多,也不存在 Web Component 的兼容性。
这三中方式的本质都是更新 DOM 的展示效果,只是方式不同而已,为了更简单的说明双向绑定的原理,我们就采用第一种方式。虚拟DOM是有很多独立的第三方库,如果有兴趣同学可以去研究哦。

解析器与DOM操作

这里的主要任务是:

  • 解析模板中所有的特定特性,例如:v-model、v-text、{{ }}语法等;
  • 关联数据展示到DOM;
  • 关联事件绑定到DOM;
  • 因此,下面的功能只能需要满足:展示数据到模板上。

代码如下:

<div id="app">
  <input v-model="value" />
  <p v-text="value"></p>
</div>
// 模板解析
function Compile(el, data) {

  // 关联自定义特性
  if (el.attributes) {
    [].forEach.call(el.attributes, attribute => {
      if (attribute.name.includes('v-')) {
        Update[attribute.name](el, data, attribute.value);
      }
    });
  }

  // 递归解析所有DOM
  [].forEach.call(el.childNodes, child => Compile(child, data));
}

// 自定义特性对应的事件
const Update = {
  "v-text"(el, data, key) {

    // 初始化DOM内容
    el.innerText = data[key];
  },
  "v-model"(input, data, key) {

    // 初始化Input默认值
    input.value = data[key];

    // 监听控件的输入事件,并更新数据
    input.addEventListener("keyup", e => {
      data[key] = e.target.value;
    });
  }
};

// ====

// 数据
const myData = { value: "hello world." };

// 解析
Compile(document.querySelector("#app"), myData);

目前我们定义的 DOM 解析,并没有关联数据监听,让我们来完成它!

完整的双向绑定

代码如下:

// 发布者
function Subject() {
  this.observers = [];
  this.attach = function(callback) {
    this.observers.push(callback);
  };
  this.notify = function(value) {
    this.observers.forEach(callback => callback(value));
  };
}

// 订阅者
function Observer(queue, key, callback) {
  queue[key].attach(callback);
}

// ====

// 数据拦截器 - 代理方式
function ProxyWatcher(data, queue) {
  return new Proxy(data, {
    get: (target, key) => target[key],
    set(target, key, value) {
      target[key] = value;

      // 通知此值的所有订阅者,数据发生了更新
      queue[key].notify(value);
    }
  });
}

// ====

// 模板解析
function Compile(el, data) {

  // 关联自定义特性
  if (el.attributes) {
    [].forEach.call(el.attributes, attribute => {
      if (attribute.name.includes('v-')) {
        Update[attribute.name](el, data, attribute.value);
      }
    });
  }

  // 递归解析所有DOM
  [].forEach.call(el.childNodes, child => Compile(child, data));
}

// 自定义特性对应的事件
const Update = {
  "v-text"(el, data, key) {

    // 初始化DOM内容
    el.innerText = data[key];

    // 创建一个数据的订阅,数据变化后更新展示内容
    Observer(messageQueue, key, value => {
        el.innerText = value;
    });
  },
  "v-model"(input, data, key) {

    // 初始化Input默认值
    input.value = data[key];

    // 监听控件的输入事件,并更新数据
    input.addEventListener("keyup", e => {
      data[key] = e.target.value;
    });

    // 创建一个订阅
    Observer(messageQueue, key, value => {
      input.value = value;
    });
  }
};

// ====

// 消息队列
const messageQueue = {};

// 数据
const myData = ProxyWatcher({ value: "hello world." }, messageQueue);

// 将每个数据属性都添加到观察者的消息队列中
for (let key in myData) {
    messageQueue[key] = new Subject();
}

// ====

// 解析+关联
Compile(document.querySelector("#app"), myData);

如此,一个非常简单的 MVVM 功能就完成了。当然,它仅仅是为了讲解原理非编写的,如果要做成向 Vue 这样的成熟框架,就需要将各个核心封装成模块,进行更扩展性的定义。
如果再简单的封装一下,看上去就是一个极简的Vue了。
代码如下:

// 观察者功能
// 发布者
function Subject() {
  this.observers = [];
  this.attach = function(callback) {
    this.observers.push(callback);
  };
  this.notify = function(value) {
    this.observers.forEach(callback => callback(value));
  };
}
// 订阅者
function Observer(queue) {
  this.queue = queue
  this.add = function(key, callback) {
    this.queue[key].attach(callback);
  }
}

// ====

// 数据拦截器
// 监听数据更新 - 代理方式
function ProxyWatcher(data, queue) {
  return new Proxy(data, {
    get: (target, key) => target[key],
    set(target, key, value) {
      target[key] = value;

      // 通知此值的所有订阅者,数据发生了更新
      queue[key].notify(value);
    }
  });
}

// ====

// 模板解析
function Compile(el, vm) {

  // 关联自定义特性
  if (el.attributes) {
    [].forEach.call(el.attributes, attribute => {
      if (attribute.name.includes('v-')) {
        Update[attribute.name](el, vm.data, attribute.value, vm);
      }
    });
  }

  // 递归解析所有DOM
  [].forEach.call(el.childNodes, child => Compile(child, vm));

  return el
}

// 自定义特性对应的事件
const Update = {
  "v-text"(el, data, key, vm) {

    // 初始化DOM内容
    el.innerText = data[key];

    // 创建一个数据的订阅,数据变化后更新展示内容
    vm.observer.add(key, value => {
      el.innerText = value;
    });
  },
  "v-model"(input, data, key, vm) {

    // 初始化Input默认值
    input.value = data[key];

    // 创建一个订阅
    vm.observer.add(key, value => {
      input.value = value;
    });

    // 监听控件的输入事件,并更新数据
    input.addEventListener("keyup", e => {
      data[key] = e.target.value;
    });
  }
};

// ====

// 封装
function Vue({ el, data }) {

  // initProxy
  this.messageQueue = {};
  this.observer = new Observer(this.messageQueue)
  this.data = ProxyWatcher(data, this.messageQueue);

  // initState
  for (let key in myData) {
    this.messageQueue[key] = new Subject();
  }

  // initRender
  // initEvents
  this.el = Compile(el, this);
}

// ====

// 数据
const myData = { value: "hello world." };

// 实例
const vm = new Vue({
  el: document.querySelector("#app"),
  data: myData
});
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
作为初学入门选择方向的好教材 许多技术人员在面对.NET Framework 3.0/3.5大量的新知识、新技术的时候感到彷徨,对自己现有的技术知识是否过时会产生疑问,对新技术会产生抵触的情绪,其实,只要能学习到真正代表业界趋势的技术,花不太多的时间掌握新技术,乐趣就会随之产生。编写本书的一个目的就是要让读者认识到.NET 3.5相关的新知识都是基于现有技术的,体会、掌握并应用这些新技术并不是难事。 本书全面讲解了.NET Framework 3.5开发各方面的技术要点,共分19章。本书没有对各个功能的工作原理进行深入的揭示,而是采用“知识进述”+“代码示例”的方式,让读者可以快速体验并掌握.NETFramework 3.5的开发方法。 本书适合从事各利.NET程序开发的人员阅读。通过不同层次的例子,相信可以让读者理解、掌握,NET程序开发,特别是关于WPF、wcF和WF这3种重要框架的应用所要掌握的知识。 第1章 .NETFramework3.5简介 1 文名: .NETFramework3.5开发技术详解 作者: 王毅.图书分类: 计算机与网络 资源格式: PDF 版本: 2009 出版社: 人民邮电出版社.书号: 9787115190918.发行时间: 2009年 地区: 大陆 语言: 简体文 简介: 1.1 .NETFramework3.5在.NET技术体系的位置 1 1.2 .NET3.5各部分的功能 2 1.3 .NET3.5的组件 3 1.3.1 WindowsPresentaionFoundation(WPF) 3 1.3.2 WindowsCommunicationFoundation(WCF) 5 1.3.3 WorkflowFoundation(WF) 6 1.4 搭建.NET3.5的开发环境 6 1.4.1 在WindowsXP/2003/Vista上搭建开发环境 6 1.4.2 相关工具 9 第2章 .NET3.5的新功能 12 2.1 .NET3.5概要 12 2.2 新的.NET基础类型 12 2.3 C#语言的强化 14 2.3.1 C#基本语法增强 14 2.3.2 LINQ(集成语言查询) 16 第3章 WindowsPresentationFoundation基础知识 34 3.1 WindowsPresentationFoundation(WPF)的概念 34 3.2 XAML的概念 35 3.2.1 命名空间 36 3.2.2 代码后置文件 37 3.2.3 调用.NET类库的类来定义对象 37 3.2.4 属性 38 3.3 WPF的结构和相关的类库 39 3.4 WPF应用程序的类型 44 3.4.1 传统类型的视窗程序 44 3.5 创建第一个WPF程序 49 第4章 WPF程序的布局 59 4.1 布局的基础知识 59 4.2 StackPanel容器 61 4.3 DockPanel容器 65 4.4 Grid容器 67 4.4.1 表格的高度和宽度 69 4.4.2 ColumnSpan和RowSpan 70 4.4.3 Grid的SharedSizeGroup 71 4.5 Canvas容器 72 4.6 文档布局 74 4.6.1 WrapPanel 74 4.6.2 TextBlock 75 4.6.3 FlowDocument 78 4.7 其他容器 83 4.8 视图控制 84 4.9 自定义布局 87 第5章 WPF的控件 91 5.1 控件模型 91 5.2 WPF的控件树 92 5.3 路由事件 95 5.4 从属属性(DependencyProperty) 97 5.5 处理交互行为 102 5.6 基本控件的使用 106 5.6.1 Button控件 106 5.6.2 TextBox类控件 109 5.6.3 列表控件 113 5.6.4 Menu控件 118 5.6.5 包容式控件 121 5.6.6 Label和TextBlock 126 5.6.7 其他控件 127 第6章 资源和数据绑定 134 6.1 在WPF定义资源 134 6.1.1 WPF的嵌入式资源 134 6.1.2 定义逻辑资源 135 6.2 使用资源 139 6.3 数据绑定基础 142 6.4 集合的绑定 151 6.5 DataProvider 157 6.6 高级数据绑定操作 165 6.7 使用CollectionViewSource进行排序和过滤 167 第7章 让WPF程序支持样式和主题 169 7.1 样式基础 169 7.1.1 WPF样式的定义 169 7.1.2 样式的作用 170 7.1.3 样式的作用范围 171 7.2 内联样式 172 7.3 命名样式 172 7.4 样式触发器 174 7.5 控件模板 180 7.6 主题 182 第8章 WPF的绘图功能 189 8.1 2D图形基础 189 8.2 2D几何图形 190 8.3 画刷和画笔 197 8.3.1 画刷 197 8.3.2 画笔 204 8.4 2D图形变换(Transform) 205 8.4.1 平移变换 205 8.4.2 缩放变换 206 8.4.3 旋转变换 206 8.4.4 斜移变换 207 8.4.5 矩阵变换 207 8.4.6 变换组(TransformGroup) 210 8.5 2D图形特效 210 8.6 3D图形基础 213 8.6.1 计算机图形学基础 213 8.6.2 WPF的3D类型 215 8.7 3D变换 218 8.8 WPF的动画支持 221 8.8.1 Animation对象 222 8.8.2 第一个动画 223 第9章 WPF的多媒体 230 9.1 对视频和音频的支持 230 9.1.1 视频支持 230 9.1.2 音频支持 235 9.2 语音功能 238 第10章 WPF高级技术 241 10.1 WPF自定义控件 241 10.1.1 编写控件的基础知识 241 10.1.2 开始编写控件 244 10.1.3 编写CustomControl控件 249 10.2 WPF的互操作性 252 10.2.1 在WPF使用Winform控件 252 10.2.2 在WInform程序使用WPF控件 254 10.3 WPF的异步模型 254 10.4 WPF对自动化程序的支持 256 10.4.1 Automation树 256 10.4.2 控件的访问方式 257 第11章 WindowsCommunicationFoundation(WCF)基础 261 11.1 面向服务编程模型(框架) 261 11.1.1 什么是SOA 261 11.1.2 为什么要使用SOA 263 11.2 WCF是什么 264 11.3 WCF的结构 265 11.4 WCF基础 267 第12章 WCF的契约 268 12.1 服务契约和操作契约 268 12.2 数据契约(DataContract) 269 12.3 错误契约(FaultContract) 272 12.4 创建WCF服务 273 12.5 编写WCF客户端 277 12.6 配置WCF程序 279 12.6.1 服务端配置 279 12.6.2 客户端配置 283 12.6.3 配置工具 284 第13章 WCF的消息交换 285 13.1 与通信有关的概念 285 13.1.1 Address(地址) 285 13.1.2 Bindings(通信绑定) 286 13.1.3 Contracts(契约) 288 13.1.4 EndPoint 292 13.2 远程对象的传递 293 13.3 大对象的传递 299 13.4 错误处理 303 13.5 会话管理 308 13.6 双向通信 311 13.7 WCF的消息编码 318 13.8 基于队列的消息交换 319 13.9 点对点网络(Peer-To-PeerNetwork) 322 第14章 并发管理 327 14.1 服务器实例行为管理 327 14.2 并发管理 330 14.3 同步上下文 332 14.4 回调的同步设置和异步调用 334 第15章 WCF的事务支持 341 15.1 事务概要 341 15.2 WCF的事务 343 15.3 创建支持事务的服务 345 第16章 WCF的安全解决方案 353 16.1 认证和授权 353 16.1.1 认证 354 16.1.2 授权 355 16.2 安全传输 360 16.2.1 传输的安全性 360 16.2.2 消息安全 363 16.3 安全策略 364 第17章 WCF的扩展性 368 17.1 服务行为的扩展 368 17.1.1 自定义分发器特性 369 17.2 自定义通道 374 17.3 自定义元数据 378 17.3.1 元数据的基本知识 378 17.3.2 扩展元数据系统 379 17.4 自定义序列化 380 第18章 WCF的运行环境 383 18.1 在IIS上启用WCF服务 383 18.2 在.NET程序运行WCF服务 386 18.3 在Windows服务程序运行WCF服务 387 第19章 工作流(WorkFlow) 392 19.1 工作流(WF)简介 392 19.1.1 工作流的概念 392 19.1.2 WindowsWorkFlowFoundation 393 19.2 Activity(活动) 396 19.3 WF运行时 401 19.4 基于状态机的工作流 405 19.5 工作流的持久化 406 19.6 工作流的XAML表示 407
作为初学入门选择方向的好教材 许多技术人员在面对.NET Framework 3.0/3.5大量的新知识、新技术的时候感到彷徨,对自己现有的技术知识是否过时会产生疑问,对新技术会产生抵触的情绪,其实,只要能学习到真正代表业界趋势的技术,花不太多的时间掌握新技术,乐趣就会随之产生。编写本书的一个目的就是要让读者认识到.NET 3.5相关的新知识都是基于现有技术的,体会、掌握并应用这些新技术并不是难事。 本书全面讲解了.NET Framework 3.5开发各方面的技术要点,共分19章。本书没有对各个功能的工作原理进行深入的揭示,而是采用“知识进述”+“代码示例”的方式,让读者可以快速体验并掌握.NETFramework 3.5的开发方法。 本书适合从事各利.NET程序开发的人员阅读。通过不同层次的例子,相信可以让读者理解、掌握,NET程序开发,特别是关于WPF、wcF和WF这3种重要框架的应用所要掌握的知识。 第1章 .NETFramework3.5简介 1 文名: .NETFramework3.5开发技术详解 作者: 王毅.图书分类: 计算机与网络 资源格式: PDF 版本: 2009 出版社: 人民邮电出版社.书号: 9787115190918.发行时间: 2009年 地区: 大陆 语言: 简体文 简介: 1.1 .NETFramework3.5在.NET技术体系的位置 1 1.2 .NET3.5各部分的功能 2 1.3 .NET3.5的组件 3 1.3.1 WindowsPresentaionFoundation(WPF) 3 1.3.2 WindowsCommunicationFoundation(WCF) 5 1.3.3 WorkflowFoundation(WF) 6 1.4 搭建.NET3.5的开发环境 6 1.4.1 在WindowsXP/2003/Vista上搭建开发环境 6 1.4.2 相关工具 9 第2章 .NET3.5的新功能 12 2.1 .NET3.5概要 12 2.2 新的.NET基础类型 12 2.3 C#语言的强化 14 2.3.1 C#基本语法增强 14 2.3.2 LINQ(集成语言查询) 16 第3章 WindowsPresentationFoundation基础知识 34 3.1 WindowsPresentationFoundation(WPF)的概念 34 3.2 XAML的概念 35 3.2.1 命名空间 36 3.2.2 代码后置文件 37 3.2.3 调用.NET类库的类来定义对象 37 3.2.4 属性 38 3.3 WPF的结构和相关的类库 39 3.4 WPF应用程序的类型 44 3.4.1 传统类型的视窗程序 44 3.5 创建第一个WPF程序 49 第4章 WPF程序的布局 59 4.1 布局的基础知识 59 4.2 StackPanel容器 61 4.3 DockPanel容器 65 4.4 Grid容器 67 4.4.1 表格的高度和宽度 69 4.4.2 ColumnSpan和RowSpan 70 4.4.3 Grid的SharedSizeGroup 71 4.5 Canvas容器 72 4.6 文档布局 74 4.6.1 WrapPanel 74 4.6.2 TextBlock 75 4.6.3 FlowDocument 78 4.7 其他容器 83 4.8 视图控制 84 4.9 自定义布局 87 第5章 WPF的控件 91 5.1 控件模型 91 5.2 WPF的控件树 92 5.3 路由事件 95 5.4 从属属性(DependencyProperty) 97 5.5 处理交互行为 102 5.6 基本控件的使用 106 5.6.1 Button控件 106 5.6.2 TextBox类控件 109 5.6.3 列表控件 113 5.6.4 Menu控件 118 5.6.5 包容式控件 121 5.6.6 Label和TextBlock 126 5.6.7 其他控件 127 第6章 资源和数据绑定 134 6.1 在WPF定义资源 134 6.1.1 WPF的嵌入式资源 134 6.1.2 定义逻辑资源 135 6.2 使用资源 139 6.3 数据绑定基础 142 6.4 集合的绑定 151 6.5 DataProvider 157 6.6 高级数据绑定操作 165 6.7 使用CollectionViewSource进行排序和过滤 167 第7章 让WPF程序支持样式和主题 169 7.1 样式基础 169 7.1.1 WPF样式的定义 169 7.1.2 样式的作用 170 7.1.3 样式的作用范围 171 7.2 内联样式 172 7.3 命名样式 172 7.4 样式触发器 174 7.5 控件模板 180 7.6 主题 182 第8章 WPF的绘图功能 189 8.1 2D图形基础 189 8.2 2D几何图形 190 8.3 画刷和画笔 197 8.3.1 画刷 197 8.3.2 画笔 204 8.4 2D图形变换(Transform) 205 8.4.1 平移变换 205 8.4.2 缩放变换 206 8.4.3 旋转变换 206 8.4.4 斜移变换 207 8.4.5 矩阵变换 207 8.4.6 变换组(TransformGroup) 210 8.5 2D图形特效 210 8.6 3D图形基础 213 8.6.1 计算机图形学基础 213 8.6.2 WPF的3D类型 215 8.7 3D变换 218 8.8 WPF的动画支持 221 8.8.1 Animation对象 222 8.8.2 第一个动画 223 第9章 WPF的多媒体 230 9.1 对视频和音频的支持 230 9.1.1 视频支持 230 9.1.2 音频支持 235 9.2 语音功能 238 第10章 WPF高级技术 241 10.1 WPF自定义控件 241 10.1.1 编写控件的基础知识 241 10.1.2 开始编写控件 244 10.1.3 编写CustomControl控件 249 10.2 WPF的互操作性 252 10.2.1 在WPF使用Winform控件 252 10.2.2 在WInform程序使用WPF控件 254 10.3 WPF的异步模型 254 10.4 WPF对自动化程序的支持 256 10.4.1 Automation树 256 10.4.2 控件的访问方式 257 第11章 WindowsCommunicationFoundation(WCF)基础 261 11.1 面向服务编程模型(框架) 261 11.1.1 什么是SOA 261 11.1.2 为什么要使用SOA 263 11.2 WCF是什么 264 11.3 WCF的结构 265 11.4 WCF基础 267 第12章 WCF的契约 268 12.1 服务契约和操作契约 268 12.2 数据契约(DataContract) 269 12.3 错误契约(FaultContract) 272 12.4 创建WCF服务 273 12.5 编写WCF客户端 277 12.6 配置WCF程序 279 12.6.1 服务端配置 279 12.6.2 客户端配置 283 12.6.3 配置工具 284 第13章 WCF的消息交换 285 13.1 与通信有关的概念 285 13.1.1 Address(地址) 285 13.1.2 Bindings(通信绑定) 286 13.1.3 Contracts(契约) 288 13.1.4 EndPoint 292 13.2 远程对象的传递 293 13.3 大对象的传递 299 13.4 错误处理 303 13.5 会话管理 308 13.6 双向通信 311 13.7 WCF的消息编码 318 13.8 基于队列的消息交换 319 13.9 点对点网络(Peer-To-PeerNetwork) 322 第14章 并发管理 327 14.1 服务器实例行为管理 327 14.2 并发管理 330 14.3 同步上下文 332 14.4 回调的同步设置和异步调用 334 第15章 WCF的事务支持 341 15.1 事务概要 341 15.2 WCF的事务 343 15.3 创建支持事务的服务 345 第16章 WCF的安全解决方案 353 16.1 认证和授权 353 16.1.1 认证 354 16.1.2 授权 355 16.2 安全传输 360 16.2.1 传输的安全性 360 16.2.2 消息安全 363 16.3 安全策略 364 第17章 WCF的扩展性 368 17.1 服务行为的扩展 368 17.1.1 自定义分发器特性 369 17.2 自定义通道 374 17.3 自定义元数据 378 17.3.1 元数据的基本知识 378 17.3.2 扩展元数据系统 379 17.4 自定义序列化 380 第18章 WCF的运行环境 383 18.1 在IIS上启用WCF服务 383 18.2 在.NET程序运行WCF服务 386 18.3 在Windows服务程序运行WCF服务 387 第19章 工作流(WorkFlow) 392 19.1 工作流(WF)简介 392 19.1.1 工作流的概念 392 19.1.2 WindowsWorkFlowFoundation 393 19.2 Activity(活动) 396 19.3 WF运行时 401 19.4 基于状态机的工作流 405 19.5 工作流的持久化 406 19.6 工作流的XAML表示 407

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值