本篇是上一篇自绘的补充,但需要一定的WPF相关知识,感谢Clingingboy 通宵达旦的帮助。

一.ScrollViewer

在前一篇我们做了一个可拖动的矩形,但你是否发现当矩形拖出背景后就不见了,一般来说对于不可见区域需要有ScrollBar来呈现,如图:

对于这一应用在WPF中最常用的应该在控件外面包个ScrollViewer,那么如何使得我们的控件支持ScrollViewer呢?

首先我们来了解一下ScrollViewer基本原理

通过上图我们可以看到ScrollViewer是以Grid为容器组成的控件,其中主要包括ScrollContentPresenter,和两个ScrollBar,其中ScrollBar就是我们第一张图中看到那两条,它也是一个由多个控件组成的复合控件,在这里先略过ScrollBar;来看红色边框内的ScrollContentPresenter,可以看到我们的控件CustomerRender在ScrollContentPresenter内,那么我们控件呈现的位置必定是由它来控制的。

这个神秘的ScrollContentPresenter到底做了什么能让我们看到一部分内容呢?看下这张图就清楚了

我们可以知道ScrollContentPresenter实际对我们玩了一个遮罩效果,把我们的控件当作一个背景图,用ScrollBar来移动背景位置,在ScrollViewer外的控件可视部分统统被裁减掉了。只要继承UIElement的控件就可以重载GetLayoutClip方法来剪切区域。

protected override Geometry GetLayoutClip(Size layoutSlotSize)
{return new RectangleGeometry(new Rect(base.RenderSize));
} 

二.ArrangeOverride

ScrollContentPresenter又是如何控制子元素的坐标呢?重载ArrangeOverride函数便可,具体看代码注释

protected override Size ArrangeOverride(Size arrangeBounds)
{//得到集合中的第一个元素 UIElement visualChild = this.GetVisualChild(0) as UIElement;//把子元素的左上角坐标定义到容器之外 Point point = new Point(-40, -50);if (visualChild != null){Rect finalRect = new Rect(point, visualChild.DesiredSize);//设置元素坐标和大小 visualChild.Arrange(finalRect);}return arrangeBounds;
} 

这段代码中参数arrangeBounds是父容器传进的值,一般表示你可以有多大的利用空间,这个函数的返回值一般指的是你控件RenderSize的大小.

RenderSize有什么用?(欢迎大家补充)

  1. 在onRender里可以用,比如画背景。
  2. 在MeasureOverride函数中当参数值为无限大时用来得知可用空间的大小。

三.MeasureOverride

visualChild.DesiredSize的值实际就是我们常用的ActualHeight和ActualWidth的源头,也就是控件的实际大小,我们可以重载MeasureOverride产生。下面是我们的自定义控件用的。

protected override Size MeasureOverride(Size constraint)
{Size size = new Size(//判断形参constraint中传的值大,还是我们的Rectangle的值大,以最大的那个作为控件的长宽Math.Max(double.IsInfinity(constraint.Width) ? this.RenderSize.Width : constraint.Width, _preivewRectangle.Right),Math.Max(double.IsInfinity(constraint.Height) ? this.RenderSize.Height : constraint.Height, _preivewRectangle.Bottom));return size;
}

要说明下的是外容器的大小并不会触发MeasureOverride(如把窗体拖大),只会触发ArrangeOverride,如果你要重新为DesiredSize赋值并通知父容器请使用Measure函数,它会调用父控件的OnChildDesiredSizeChanged方法来通知,同理父控件要监听子控件的大小变化只要重载该方法即可,这个方法可以一直沿着可视树向上引发InvalidateMeasure函数,InvalidateMeasure通过DispatcherPriority为Render来异步调用Measure。

       ArrangeOverride中尽量不要调用本身的Measure,Measure函数会再次调用InvalidateArrange方法从而引起循环。控件容器放生变化时可以重载OnRenderSizeChanged实现。

Measure和Arrange的具体关系如下图:

四.补充

如果想要自定义的ScrollBar你可以能要根绝ScrollBar的值实时进行重绘图,这个好处是数据量大,你只需呈现当前画面中的图形,缺点是动一动就要重绘。通过例如ScrollViewer裁减的方式,遮罩得时候不会重绘,不过刚开始呈现的时候数据量大会慢。

另外在复合控件中配合Transform中的各种类来进行布局,使用CompositionTarget和动画类可以产生很多效果。

本例下载

转载请注明

转载于:https://www.cnblogs.com/Curry/archive/2009/04/16/1437092.html

WPF自定义控件 —— 布局相关推荐

  1. WPF 自定义控件-布局控件

    自定义布局控件 1.添加自定义控件 添加新项->WPF->自定义控件(WPF) 在Themes文件夹下Generic.xaml会自动生成自定义控件的模板样式 2.实现自定义布局控件功能 1 ...

  2. WPF 自定义控件的坑(蠢的:自定义控件内容不显示)

    WPF 自定义控件的坑(蠢的:自定义控件内容不显示) 原文:WPF 自定义控件的坑(蠢的:自定义控件内容不显示) 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csd ...

  3. [WPF自定义控件库]自定义Expander

    [WPF自定义控件库]自定义Expander 原文:[WPF自定义控件库]自定义Expander 1. 前言 上一篇文章介绍了使用Resizer实现Expander简单的动画效果,运行效果也还好,不过 ...

  4. WPF自定义控件(四)の自定义控件

    原文:WPF自定义控件(四)の自定义控件 在实际工作中,WPF提供的控件并不能完全满足不同的设计需求.这时,需要我们设计自定义控件. 这里LZ总结一些自己的思路,特性如下: Coupling UITe ...

  5. WPF自定义控件的自定义属性绑定后不更新问题

    WPF自定义控件的自定义属性绑定后不更新问题 原文:WPF自定义控件的自定义属性绑定后不更新问题 需要在绑定时设置属性变更触发 UpdateSourceTrigger=PropertyChanged ...

  6. WPF自定义控件与样式(8)-ComboBox与自定义多选控件MultComboBox

    一.前言 申明:WPF自定义控件与样式是一个系列文章,前后是有些关联的,但大多是按照由简到繁的顺序逐步发布的等,若有不明白的地方可以参考本系列前面的文章,文末附有部分文章链接. 本文主要内容: 下拉选 ...

  7. 【转】WPF自定义控件与样式(3)-TextBox RichTextBox PasswordBox样式、水印、Label标签、功能扩展...

    一.前言.预览 申明:WPF自定义控件与样式是一个系列文章,前后是有些关联的,但大多是按照由简到繁的顺序逐步发布的等. 本文主要是对文本输入控件进行样式开发,及相关扩展功能开发,主要内容包括: 基本文 ...

  8. WPF自定义控件与样式(1)-矢量字体图标(iconfont)

    原文:WPF自定义控件与样式(1)-矢量字体图标(iconfont) 一.图标字体 图标字体在网页开发上运用非常广泛,具体可以网络搜索了解,网页上的运用有很多例子,如Bootstrap.但在C/S程序 ...

  9. WPF自定义控件与样式(5)-Calendar/DatePicker日期控件自定义样式及扩展

    原文:WPF自定义控件与样式(5)-Calendar/DatePicker日期控件自定义样式及扩展 一.前言 申明:WPF自定义控件与样式是一个系列文章,前后是有些关联的,但大多是按照由简到繁的顺序逐 ...

最新文章

  1. fiddler几种功能强大的用法(一)转自:http://www.cnblogs.com/chenshaoping/p/5785010.html
  2. 数据增强:数据有限时如何使用深度学习 ?
  3. Oracle迁移索引
  4. 前端的请求最大线程数是多少啊_面试官:创建多少个线程合适,我该怎么说?...
  5. SQL Server使用convert对datetime日期数据进行获取
  6. MongoDB工具MagicMongoDBTool使用介绍(一) -- 简单MongoDB入门
  7. springboot2 - 坑 - 解决put提交接收不到参数的问题
  8. Cgroups控制cpu,内存,io示例
  9. 服务器lsass占用内存_服务器内存跑满是什么原因造成的呢?
  10. springboot房屋租赁管理系统
  11. 用Asp.net 就能轻松实现铁道部的订票系统
  12. 安卓4.4刷linux系统下载,在Linux上安装Android 4.4 KitKat
  13. Dedecms TAG中文标签改成英文+数字地址的方法
  14. 大力哥谈 DALI - DALI 调光电源怎么用
  15. 谈谈步进电机的优点与缺点
  16. element 合计
  17. 汽车电子的发展简介和V型开发模式
  18. 二分类问题中的评价指标
  19. xbox控制台小帮手怎么卸载?
  20. 一名普通考生过去一年的考研经历

热门文章

  1. ip subnet-zero 和ip classless 的用法
  2. php带参数跳转页面,如何带参数跳转php界面_后端开发
  3. Derby与mysql的关系_Derby数据库简单介绍和使用方法 | 学步园
  4. div不继承父类样式_Java三大特性之继承
  5. 数据科学入门与实战:Seaborn001
  6. 计算机组成原理树状图,数据结构
  7. matlab命令大全,Matlab------------命令大全2
  8. c语言 结构体 选择题,C语言结构体共用体选择题(新).doc
  9. 特征筛选2——皮尔逊相关系数筛选(单变量筛选)
  10. 由windows/linux转向使用Mac的适应期教程