
System.Windows.Media.Visual
定义一个系统后,下一步是将像素绘制到屏幕上。Visual 类用于生成可视化对象的树,每个对象可以选择性地包含绘制指令以及有关如何呈现这些指令(剪辑、变换等)的元数据。Visual 设计为极其轻量且灵活,所以大部分功能未进行 API 公开,并且极为依赖受保护的回调函数。
Visual 实际上是到 WPF 组合系统的入口点。Visual 是以下两个子系统之间的连接点:托管 API 和非托管 milcore。
WPF 通过遍历由 milcore 管理的非托管数据结构来显示数据。这些结构(称为组合节点)代表层次结构显示树,其中每个节点都有呈现指令。只能通过消息传递协议来访问此树(下图右侧所示)。
当对 WPF 编程时,您将创建 Visual 元素及派生的类型,它们通过此消息传递协议在内部与此组合树进行通信。WPF 中的每个 Visual 可以不创建组合节点,也可以创建一个或多个组合节点。
请注意一个非常重要的体系结构细节 – 可视对象和绘制指令的整个树都要进行缓存。在图形方面,WPF 使用一个保留的呈现系统。这可以使系统以一个高刷新率重绘系统,并且不会发生组合系统阻止对用户代码的回调。这有助于防止出现应用程序无响应的情况。
关系图中不十分引人注意的另一个重要细节是系统实际上如何执行组合。
在 User32 和 GDI 中,系统是在一个即时模式剪辑系统上工作。当需要呈现一个组件时,系统会建立一个剪辑边界,不允许组件接触该边界之外的像素,然后会要求此组件在该框中绘制像素。此系统在内存受限的系统上工作良好,因为当某些内容更改时,只需要处理受影响的组件即可 – 不会有两个组件对一个像素的颜色更改起作用。
WPF 使用“绘画器的算法”绘制模型。这意味着并不是剪辑每个组件,而是要求从显示内容的背面至正面来呈现每个组件。这允许每个组件在先前的组件的显示内容上绘制。此模型的优点是您可以生成部分透明的复杂形状。与现今的现代图形硬件比较,此模型相对要快(创建 User32/ GDI 的情况除外)。
如上面所述,WPF 的一个核心原理是移动到一个更具声明性且“以属性为核心”的编程模型。在可视化系统中,这会表现为需要关注的两种情况。
首先,如果您考虑保留的模式图形系统,则实际上是从命令性 DrawLine/DrawLine 类型模型移动到面向数据的模型 new Line()/new Line()。通过这一向数据驱动的呈现移动,可以在使用属性表达的绘制指令上进行复杂的操作。从 Drawing 派生的类型实际上是用于呈现的对象模型。
第二,如果评估动画系统,您将看到它几乎是完全声明性的。无需要求开发人员计算下一位置或下一颜色,您可以将动画表示为动画对象上的一组属性。于是,这些动画可以表示开发人员或设计人员的意图(在 5 秒内将此按钮从一个位置移动到另一个位置),系统就可以确定完成此任务的最有效方式。