WPF自定义控件 —— 布局
本篇是上一篇自绘的补充,但需要一定的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有什么用?(欢迎大家补充)
- 在onRender里可以用,比如画背景。
- 在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自定义控件 —— 布局相关推荐
- WPF 自定义控件-布局控件
自定义布局控件 1.添加自定义控件 添加新项->WPF->自定义控件(WPF) 在Themes文件夹下Generic.xaml会自动生成自定义控件的模板样式 2.实现自定义布局控件功能 1 ...
- WPF 自定义控件的坑(蠢的:自定义控件内容不显示)
WPF 自定义控件的坑(蠢的:自定义控件内容不显示) 原文:WPF 自定义控件的坑(蠢的:自定义控件内容不显示) 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csd ...
- [WPF自定义控件库]自定义Expander
[WPF自定义控件库]自定义Expander 原文:[WPF自定义控件库]自定义Expander 1. 前言 上一篇文章介绍了使用Resizer实现Expander简单的动画效果,运行效果也还好,不过 ...
- WPF自定义控件(四)の自定义控件
原文:WPF自定义控件(四)の自定义控件 在实际工作中,WPF提供的控件并不能完全满足不同的设计需求.这时,需要我们设计自定义控件. 这里LZ总结一些自己的思路,特性如下: Coupling UITe ...
- WPF自定义控件的自定义属性绑定后不更新问题
WPF自定义控件的自定义属性绑定后不更新问题 原文:WPF自定义控件的自定义属性绑定后不更新问题 需要在绑定时设置属性变更触发 UpdateSourceTrigger=PropertyChanged ...
- WPF自定义控件与样式(8)-ComboBox与自定义多选控件MultComboBox
一.前言 申明:WPF自定义控件与样式是一个系列文章,前后是有些关联的,但大多是按照由简到繁的顺序逐步发布的等,若有不明白的地方可以参考本系列前面的文章,文末附有部分文章链接. 本文主要内容: 下拉选 ...
- 【转】WPF自定义控件与样式(3)-TextBox RichTextBox PasswordBox样式、水印、Label标签、功能扩展...
一.前言.预览 申明:WPF自定义控件与样式是一个系列文章,前后是有些关联的,但大多是按照由简到繁的顺序逐步发布的等. 本文主要是对文本输入控件进行样式开发,及相关扩展功能开发,主要内容包括: 基本文 ...
- WPF自定义控件与样式(1)-矢量字体图标(iconfont)
原文:WPF自定义控件与样式(1)-矢量字体图标(iconfont) 一.图标字体 图标字体在网页开发上运用非常广泛,具体可以网络搜索了解,网页上的运用有很多例子,如Bootstrap.但在C/S程序 ...
- WPF自定义控件与样式(5)-Calendar/DatePicker日期控件自定义样式及扩展
原文:WPF自定义控件与样式(5)-Calendar/DatePicker日期控件自定义样式及扩展 一.前言 申明:WPF自定义控件与样式是一个系列文章,前后是有些关联的,但大多是按照由简到繁的顺序逐 ...
最新文章
- fiddler几种功能强大的用法(一)转自:http://www.cnblogs.com/chenshaoping/p/5785010.html
- 数据增强:数据有限时如何使用深度学习 ?
- Oracle迁移索引
- 前端的请求最大线程数是多少啊_面试官:创建多少个线程合适,我该怎么说?...
- SQL Server使用convert对datetime日期数据进行获取
- MongoDB工具MagicMongoDBTool使用介绍(一) -- 简单MongoDB入门
- springboot2 - 坑 - 解决put提交接收不到参数的问题
- Cgroups控制cpu,内存,io示例
- 服务器lsass占用内存_服务器内存跑满是什么原因造成的呢?
- springboot房屋租赁管理系统
- 用Asp.net 就能轻松实现铁道部的订票系统
- 安卓4.4刷linux系统下载,在Linux上安装Android 4.4 KitKat
- Dedecms TAG中文标签改成英文+数字地址的方法
- 大力哥谈 DALI - DALI 调光电源怎么用
- 谈谈步进电机的优点与缺点
- element 合计
- 汽车电子的发展简介和V型开发模式
- 二分类问题中的评价指标
- xbox控制台小帮手怎么卸载?
- 一名普通考生过去一年的考研经历
热门文章
- ip subnet-zero 和ip classless 的用法
- php带参数跳转页面,如何带参数跳转php界面_后端开发
- Derby与mysql的关系_Derby数据库简单介绍和使用方法 | 学步园
- div不继承父类样式_Java三大特性之继承
- 数据科学入门与实战:Seaborn001
- 计算机组成原理树状图,数据结构
- matlab命令大全,Matlab------------命令大全2
- c语言 结构体 选择题,C语言结构体共用体选择题(新).doc
- 特征筛选2——皮尔逊相关系数筛选(单变量筛选)
- 由windows/linux转向使用Mac的适应期教程