《Programming WPF》翻译 第7章 5.可视化层编程
原文:《Programming WPF》翻译 第7章 5.可视化层编程
形状元素能提供一种便利的方式与图形一起工作,在一些情形中,添加表示绘图的元素到UI树中,可能是比它的价值更加麻烦。你的数据可能被构造以一种易于编写代码的方式——简单地表现一系列基于数据的绘图操作,而不是构造一棵对象树。
WPF提供一个“可视化层”API,作为一个对形状元素较低级别的折中。(实际上,形状元素全都在可视化层得顶部被实现。)这个API使我们编写按需生成的代码。
可视化是一个可见的对象。WPF应用程序的外观是将它所有的可视化组合到屏幕上形成的。由于WPF生成在在可视化层的顶级,每个元素都是可视化的。FrameworkElement基类间接派生于Visual。在可视化层编程,简单地解决了创建一个可视化和编写代码告诉WPF我们想要在可视化中显示什么。
即使在这个低的级别,WPF的表现非常不同于Win32。图形加速的方式是托管的,这意味着你的按需生成的代码很少被调用——少于在经典Windows应用程序中。
7.5.1 按需生成
按需生成的关键定制为OnRender方法。这个方法被WPF调用在它需要你的组件生成它的外观时。(这是内嵌形状的类生成它们自身的方式。)
OnRender虚方法定义在OnDemandVisual类。大多数元素都间接的通过FrameworkElement派生于此,这就增加了核心样式如外观和输入处理。
示例7-47显示了一个字定义的元素,覆写了OnRender。
示例7-47
public class CustomRender : FrameworkElement


{
    protected override void OnRender(DrawingContext drawingContext)

    
{
        Debug.WriteLine("OnRender");

        base.OnRender(drawingContext);

        drawingContext.DrawRectangle(Brushes.Red, ));

        FormattedText text = new FormattedText("Hello, world",
            CultureInfo.CurrentUICulture, FlowDirection.LeftToRightThenTopToBottom,
            , Brushes.Black);
        drawingContext.DrawText(text, ));
    }

}
注意到DrawingContext使用了Brush和Pen类来指出形状是如何填充和画轮廓的,正如我们之前看到的高级别形状对象。我们还可以传递同样的Geometry和Drawing对象——也是在本章前面看到的。
| 
 Operation  | 
 Usage  | 
|---|---|
| 
 DrawDrawing  | 
 Draws a Drawing object.  | 
| 
 DrawEllipse  | 
 Draws an ellipse.  | 
| 
 DrawGeometry  | 
 Draws any Geometry object.  | 
| 
 DrawGlyphRun  | 
 Draws a series of glyphs (i.e., text elements) offering detailed control over typography.  | 
| 
 DrawImage  | 
 Draws a bitmap image.  | 
| 
 DrawLine  | 
 Draws a line (a single segment).  | 
| 
 DrawRectangle  | 
 Draws a rectangle.  | 
| 
 DrawRoundedRectangle  | 
 Draws a rectangle with rounded corners.  | 
| 
 DrawText  | 
 Draws text.  | 
| 
 DrawVideo  | 
 Draws a rectangular region that can display video.  | 
| 
 PushTransform  | 
 Sets a transform that will be applied to all subsequent drawing operations until Pop is called; if a transform is already in place, the net effect will be the combination of all the transforms currently pushed.  | 
| 
 PushClip  | 
 Sets a clip region that will be applied to all subsequent drawing operations until Pop is called; as with PushTransform, multiple active clip regions will combine.  | 
| 
 PushOpacity  | 
 Sets a level of opacity that will be applied to all subsequent drawing operations until Pop is called; as with transforms and clips, multiple opacities are combined.  | 
| 
 Pop  | 
 Removes the transform, clip region, or opacity added most recently by PushTransform, PushClip, or PushOpacity. If those methods have been called multiple times, calls to Pop remove their effects in reverse order. (The transforms, clip regions, and opacities behave like a stack.)  | 
因为我们的自定义元素派生于FrameworkElement,它自然地集成到任何WPF应用程序中。示例7-48为一个窗体的标记,其中包含了自定义元素,我们可以使用它就像我们之前使用的任何自定义元素。这个窗体如图7-56所示。
示例7-48
 图7-56
<?Mapping XmlNamespace="controls" ClrNamespace="VisualRender" ?>
<Window x:Class="VisualRender.Window1"
    xmlns="http://schemas.microsoft.com/winfx/avalon/2005"
    xmlns:x="http://schemas.microsoft.com/winfx/xaml/2005"
    xmlns:cc="controls"
    Text="Visual Layer Rendering"
    >
    <Canvas>
        " x:Name="customRender" />
    </Canvas>
</Window>

注意到,示例7-47中的OnRender方法调用了Debug.WriteLine。如果程序运行在VS2008调试器的内部,这将在每次调用OnRender方法的时候,打印出一条消息到“输出”窗体。这支持我们看到WPF如何经常要求我们的自定义可视化来生成它自身。如果你习惯于如何在在标准Win32和Windows Forms中的按需绘制下工作,你可能希望看到这被规则地调用——无论窗体重新调整大小还是部分模糊或隐藏。实际上,它只会被调用一次。
结果是按需生成并不相似于Win32的旧有样式生成,正如你可能想到的。WPF会调用你的OnRender方法当它需要知道你的可视化显示什么内容,但是图形加速的工作方式意味着这种情况的发生远远少于Win32中等价的重画。WPF缓存了生成指令。这种缓存的范围和形式并没有文本化,但是它清晰的发生了。进一步而言,这比简单的基于图像的缓存要微妙的多。我们可以添加这些代码到示例7-48的宿主窗体(在后台代码文件中可能是这样的)。
 protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e)
 
{
         VisualOperations.SetTransform(CustomRender, ));
 }先前的片断应用了转换到我们的元素,以因数6放大。当点击用户界面时,自定义可视化会如你想希望的方式延伸,而且OnRender并没有被调用。不仅如此,放大的可视化并没有显示任何你可以看到的像素化或模糊化的人造物,通过一个简单的图像缩放。它继续是锐利的,正如你在图7-57看到的。
图7-57

这指出了WPF获取关于可视化内容的缩放信息。它能重绘我们的可视化的屏幕外观,而不使用我们的OnRender方法,即使当转换有所改变。这在局部上取决于加速构架,而且同样因为转换支持在大多数基础的级别生成在WPF中。
WPF重绘的能力——不使用OnRender,允许用户界面在屏幕上保持完整,即使我们的应用程序很繁忙。它同样支持动画系统工作而不用很多来自应用程序的干扰,因为所有的基础绘制操作都被保留了,WPF可以重建任何部分的UI——当独立的元素改变的时候。
如果我们对象的状态必须在某种程度上改变——需要更新外观,我们可以调用InvalidateVisual方法。这将导致WPF调用我们的OnRender方法,允许我们重建外观。
注意到,当你重写OnRender的时候,你还应该典型地覆写MeasureOverrid和ArrangeOverride方法。否则,WPF的外观系统不会知道你的元素有多大。我们得到的唯一原因,而不用在这里这么做,是我们在Canvas上使用该元素,这将不会关心它的子元素有多大。为了在其它的面板上工作,这是实质的让外观系统知道你的大小。第二章描述了MeasureOverrid和ArrangeOverride方法。
《Programming WPF》翻译 第7章 5.可视化层编程的更多相关文章
- [Real World Haskell翻译]第24章 并发和多核编程 第一部分并发编程
		
第24章 并发和多核编程 第一部分并发编程 当我们写这本书的时候,CPU架构正在以比过去几十年间更快的速度变化. 并发和并行的定义 并发程序需要同时执行多个不相关任务.考虑游戏服务器的例子:它通常是由 ...
 - 《Programming WPF》翻译 目录
		
原文:<Programming WPF>翻译 目录 注:第1.2章我只做了笔记,没有翻译,请大家阅读时注意. 还有就是,这本书的英文版本下载:[O'Reilly] Programming ...
 - 《Programming WPF》翻译 第9章 5.默认可视化
		
原文:<Programming WPF>翻译 第9章 5.默认可视化 虽然为控件提供一个自定义外观的能力是有用的,开发者应该能够使用一个控件而不用必须提供自定义可视化.这个控件应该正好工作 ...
 - 《Programming WPF》翻译 第9章 6.我们进行到哪里了?
		
原文:<Programming WPF>翻译 第9章 6.我们进行到哪里了? 只有当任何内嵌控件都没有提供你需要的底层行为时,你将要写一个自定义控件.当你写一个自定义控件,你将要使用到依赖 ...
 - 《Programming WPF》翻译 第9章 4.模板
		
原文:<Programming WPF>翻译 第9章 4.模板 对一个自定义元素最后的设计考虑是,它是如何连接其可视化的.如果一个元素直接从FrameworkElement中派生,这将会适 ...
 - 《Programming WPF》翻译 第9章 3.自定义功能
		
原文:<Programming WPF>翻译 第9章 3.自定义功能 一旦你挑选好一个基类,你将要为你的控件设计一个API.大部分WPF元素提供属性暴露了多数功能,事件,命令,因为他们从框 ...
 - 《Programming WPF》翻译 第9章 2.选择一个基类
		
原文:<Programming WPF>翻译 第9章 2.选择一个基类 WPF提供了很多类,当创建一个自定义元素时,你可以从这些类中派生.图9-1显示了一组可能作为类--可能是合适的基类, ...
 - 《Programming WPF》翻译 第9章 1.自定义控件基础
		
原文:<Programming WPF>翻译 第9章 1.自定义控件基础 在写一个自定义控件之前,你需要问的第一个问题是,我真的需要一个自定义控件吗?一个写自定义控件的主要原因是为了用户界 ...
 - 《Programming WPF》翻译 第8章 4.关键帧动画
		
原文:<Programming WPF>翻译 第8章 4.关键帧动画 到目前为止,我们只看到简单的点到点的动画.我们使用了To和From属性或者By属性来设计动画--相对于当前的属性值.这 ...
 
随机推荐
- git 查看文件修改记录
			
今天追了个几年前留下来的坑, 在 git 里追溯修改过程坑死个爹, 具体方法估计没多久又会忘, 还是记下来以后有的参考 大部分教程都会告诉大家使用 git log 来查看对应文件的修改记录, 就像这样 ...
 - [置顶] 【cocos2d-x入门实战】微信飞机大战之十三:游戏场景过渡
			
原创作品,转载请标明:http://blog.csdn.net/jackystudio/article/details/12082043 游戏是实现了,但是如果有个欢迎界面和一个结束界面就更好了. 欢 ...
 - QQ能上,但是网页打不开的解决办法
			
QQ能上,但是网页打不开,解决办法是:netsh winsock reset
 - iOS 原生二维码扫描,带扫描框和扫描过程动画
			
在代码中使用了相对布局框架Masonry 准备两张图片,一张是扫描边框,一张是扫描时的细线分别命名 scanFrame.png和scanLine.png并提前放入工程 导入相对布局头文件 #defin ...
 - 初入Python继承
			
1.什么是继承? 新类不用从头编写 新类从现有的类继承,就自动拥有了现有类的所有功能 新类只需要编写现有类缺少的新功能 2.继承的好处 复用已有代码 自动拥有了现有类的所有功能 只需要编写缺少的新功能 ...
 - [Redux] Extracting Container Components -- Complete
			
Clean TodoApp Component, it doesn't need to receive any props from the top level component: const To ...
 - Dynamics CRM 常用 C# 方法集合
			
Plugin(C#) 分派 AssignRequest assign = new AssignRequest(); assign.Assignee = prEntity["ownerid&q ...
 - Eclipse UML插件AmaterasUML的配置及使用
			
AmaterasUML是个人觉得最好用的Eclipse UML插件,可以通过拖拽Java源文件,轻松生成类图结构,同时支持活动图.时序图和用例图.它的官方下载地址是:http://sourceforg ...
 - oracle的启动和关闭
			
一.sql*plus方式: 用sql*plus来连接到Oracle Sqlplus /nolog 是以不连接数据库的方式启动sql*plus Connect /as sysdba 是以DBA ...
 - css布局详解(一)——盒模型
			
一.网页布局的几种情况 今天让我们总结一下在css布局的各种情况做一个总结,为我们以后布局网页时做一个参考. 先看一张图,这是去年cssConf大会时阿里的 @寒冬winter 老师放出来的: 如图所 ...