在WPF中,如果需要绘制大量图形元素,并且对性能要求严苛的话,最好使用DrawingVisual,当然,你也可以选用

Path类和比Path类更轻量级的Geometry(几何形状)来实现你的需求,但是开销会比DrawingVisual来的大。

DrawingVisual继承自ContainerVisual,该类有一个RenderOpen方法,返回一个可用于定义可视化内容的DrawingContext对象,绘制完毕后需要调用DrawingContext.Close()方法来结束绘图。

DrawingContext中有各种绘图的方法,包括DrawLine,DrawRectangle,DrawText等等,今天我们举一个较复杂的例子DrawGeometry().

在此之前,我们需要做一些准备工作:参考自<WPF编程宝典>第三部分--图画和动画--330页

1.为元素调用AddVisualChild()和AddLogicalChild()方法来注册可视化元素

2.重写VisualChildrenCount属性和重写GetVisualChild()方法,本质上是劫持了那个元素,如果使用一些能包含控件的例如Panel,Window,则这些panel,window中除了DrawingVisual,其他的控件将不再可见。

代码如下:

 public partial class MainWindow : Window
{
private DrawingVisual _drawingVisual = new DrawingVisual();
public MainWindow()
{
InitializeComponent();
this.AddVisualChild(_drawingVisual);
var dc = _drawingVisual.RenderOpen();
PathFigure pthFigure = new PathFigure();
pthFigure.IsClosed = false; //是否封闭
pthFigure.IsFilled = false; //是否填充
pthFigure.StartPoint = new Point(10, 100); System.Windows.Point Point1 = new System.Windows.Point(10, 100);
System.Windows.Point Point2 = new System.Windows.Point(100, 200);
System.Windows.Point Point3 = new System.Windows.Point(200, 30);
System.Windows.Point Point4 = new System.Windows.Point(250, 200);
System.Windows.Point Point5 = new System.Windows.Point(200, 150); PolyLineSegment plineSeg = new PolyLineSegment();
plineSeg.Points.Add(Point1);
plineSeg.Points.Add(Point2);
plineSeg.Points.Add(Point3);
plineSeg.Points.Add(Point4);
plineSeg.Points.Add(Point5); PathSegmentCollection myPathSegmentCollection = new PathSegmentCollection();
myPathSegmentCollection.Add(plineSeg); pthFigure.Segments = myPathSegmentCollection; PathFigureCollection pthFigureCollection = new PathFigureCollection(); pthFigureCollection.Add(pthFigure); PathGeometry pthGeometry = new PathGeometry(); pthGeometry.Figures = pthFigureCollection; dc.DrawGeometry(Brushes.White, new Pen(Brushes.White,1), pthGeometry); dc.Close();
}
//必须重载这两个方法,不然是画不出来的
// 重载自己的VisualTree的孩子的个数,由于只有一个DrawingVisual,返回1
protected override int VisualChildrenCount
{
get { return 1; }
} // 重载当WPF框架向自己要孩子的时候,返回返回DrawingVisual
protected override Visual GetVisualChild(int index)
{
if (index == 0)
return _drawingVisual; throw new IndexOutOfRangeException();
}
}

WPF还为DrawingVisual提供了可以命中测试,用以实现点击,拖拽等功能,主要是依靠方法VisualTreeHelper.HitTest,

我尝试着用了下,这个方法比较消耗性能,而且只适合那种面积较大的按钮,方块,一点就中的情况,如果是一条线或者一个小点,则很难点击命中。我会建议使用Path,自带了各种鼠标事件。这个在WPF编程宝典中有详解,不再赘述!

如果既需要大量的图形,又需要能支持鼠标事件的控件,我建议的做法是,在Grid中放置Panel用于绘制DrawingVisual,然后在放置Canvas来内置各种控件。Panel和Canvas重叠起来。

未完待续。。。。。。。。

WPF DrawingVisual详解的更多相关文章

  1. WPF数据绑定详解

    元素绑定 数据绑定最简单的形式是,源对象是WPF元素而且源属性是依赖属性.依赖项属性具有内置的更改通知支持,当在源对象中改变依赖项属性的值时,会立即更新目标对相中的绑定属性. <!--Xaml程 ...

  2. WPFの触发器详解

    例子1 简单触发器Triggers——满足简答的条件,触发 <Window x:Class="Styles.SimpleTriggers" xmlns="http: ...

  3. wpf附加属性详解

    为什么使用附加属性 附加属性的一个用途是允许不同的子元素为父元素中定义的属性指定唯一的值. 此方案的一个具体应用是,让子元素通知父元素它们在用户界面 (UI) 中的呈现方式. 一个示例是 DockPa ...

  4. WPF依赖属性详解

    WPF依赖属性详解 WPF 依赖属性 英文译为 Dependency Properties,是WPF引入的一种新类型的属性,在WPF中有着极为广泛的应用,在WPF中对于WPF Dependency P ...

  5. wpf 客户端【JDAgent桌面助手】开发详解(四) popup控件的win8.0的bug

    目录区域: 业余开发的wpf 客户端终于完工了..晒晒截图 wpf 客户端[JDAgent桌面助手]开发详解-开篇 wpf 客户端[JDAgent桌面助手]详解(一)主窗口 圆形菜单... wpf 客 ...

  6. wpf 客户端【JDAgent桌面助手】开发详解(三) 瀑布流效果实现与UI虚拟化优化大数据显示

    目录区域: 业余开发的wpf 客户端终于完工了..晒晒截图 wpf 客户端[JDAgent桌面助手]开发详解-开篇 wpf 客户端[JDAgent桌面助手]详解(一)主窗口 圆形菜单... wpf 客 ...

  7. wpf中的触发器详解 (转自 乂乂的日志 - 网易博客)

    2010-03-24 16:19:07|  分类: WPF相关 |  标签: |字号大中小 订阅     wpf中的触发器详解 WPF/C# 2009-08-24 11:32:50 7.1.2  简单 ...

  8. wpf 客户端【JDAgent桌面助手】开发详解-开篇

    上周二 发表了一个帖子:wpf 客户端[JDAgent桌面助手]业余开发的终于完工了..晒晒截图... 没有想到不到一个周时间已经浏览量过8千,估计过几天就过万了..很开心啊.. 评论中好多网友问我要 ...

  9. wpf 客户端【JDAgent桌面助手】开发详解(一)主窗口 圆形菜单

    目录区域: wpf 客户端[JDAgent桌面助手]业余开发的终于完工了..晒晒截图wpf 客户端[JDAgent桌面助手]开发详解-开篇 内容区域: 这里开始主窗口 圆形菜单制作的过程,首先请大家看 ...

随机推荐

  1. [CQOI2009]叶子的染色【性质+树形Dp】

    Online Judge:Bzoj1304,Luogu P3155 Label:无根树,树形Dp 题目描述 给定一棵\(N\)个节点的无根树,它一共有\(K\)个叶子节点.你可以选择一个度数大于1的节 ...

  2. 关于判断是安卓还是ios环境跳转下载页

    H5项目中判断是安卓还是iOS手机就跳转到不同的下载页,项目如下https://github.com/JserJser/dailyPush/tree/master/daily6/H5 这个项目里面我比 ...

  3. pickle序列化一个函数,将fun()取出文件

    pickle序列化一个函数,将fun()取出文件

  4. [编织消息框架][JAVA核心技术]数值与逻辑分离

    为什么要分离? 业务需求是不停地变,如果把条件写进代码里,当用户需求变时要改代码发版本更新才能生效,这过程无疑是漫长的 就算是在开发期,不停的变开发者精力耗光在沟通,小修改上,无法专注逻辑部分 分离的 ...

  5. 原 ASP.net out 和ref之间的区别

    ref和out都是C#中的关键字,所实现的功能也差不多,都是指定一个参数按照引用传递.对于编译后的程序而言,它们之间没有任何区别,也就是说它们只有语法区别.总结起来,他们有如下语法区别: 1.ref传 ...

  6. python intern(字符串驻留机制)

    python 中为了提高字符串的使用用效率和节约内存,对于由 字母.数字.下划线组成的标识符采用了 intern 机制,即对于短字符串,将其赋值给多个对象时,内存中只有一个副本,多个对象共享这个副本. ...

  7. VC++1.5太伟大了

    功能样样俱全,一点不比现在的VS系列差 VC++1.5全貌,虽然很古老,但是已经可以了. 新建的文档试图,多文档工程,很像样 文档试图,单文档工程,已经非常像样了,和记事本差不多了 这是资源编辑器,寒 ...

  8. spring MVC4 配置详解(个人记录)

    <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.sp ...

  9. Vuejs实战项目三:退出系统功能实现

    1.创建Mockjs接口 method:post url:/user/logout 描述:退出系统 response: { "code": 2000, //状态码 "fl ...

  10. Leetcode165. Compare Version Numbers比较版本号

    比较两个版本号 version1 和 version2. 如果 version1 > version2 返回 1,如果 version1 < version2 返回 -1, 除此之外返回  ...