一、开发背景
近期在项目中要用到GroupBox,结果发现Avalonia原生框架中竟然没有这一控件。想着这个控件也不算复杂,索性就自己实现一个好了。
二、坑的开始
熟悉桌面开发的朋友一定对下面这个经典的GroupBox样式不陌生——
这个样式看似简单,实则也不难实现。只要解决对标题处边框的擦除或遮盖这一个小问题就可以了。在WPF中,是用了OpacityMask来实现的。而在Avalonia中,仍然保留了这一属性,使得我们能很轻松地实现控件模板的移植。
但是事实真的这样吗?
当我把GroupBox的原生模板移植到Avalonia中,并且原模原样地实现了一个BorderGapMaskConverter之后,我发现该模板并不能正常工作。于是我单独写了个关于Border边框部分遮挡的用例,才发现DrawingBrush/VisualBrush并不能给OpacityMask使用,会发生如下报错:
Unable to cast object of type 'Avalonia.Media.DrawingBrush' to type 'Avalonia.Media.IImmutableBrush
后来在github上的源码仓库下也发现有人提了相同的issue,但似乎到今日仍未解决。。。
三、开辟新思路
既然用遮罩的方式没办法实现,那不如就单纯画一个带有缺口的边框好了!
四、实现过程
1、先编写一个缺口矩形生成器,使用Geometry的图形生成指令
public static Geometry GetRoundedRectangleWithGap(Rect rect, double radiusX, double radiusY, double gapValue1, double gapValue2, Dock gapDock = Dock.Top)
{
StreamGeometry streamGeometry = new StreamGeometry();
using (StreamGeometryContext streamGeometryContext = streamGeometry.Open())
{
var arcSize = new Size(radiusX, radiusY);
var startPoint = new Point(Math.Max(gapValue1, gapValue2), rect.Top);
var endPoint = new Point(Math.Min(gapValue1, gapValue2), rect.Top);
streamGeometryContext.BeginFigure(startPoint, true);
streamGeometryContext.LineTo(new Point(rect.Right - radiusX, rect.Top));
streamGeometryContext.ArcTo(new Point(rect.Right, rect.Top + radiusY), arcSize, PiO
标签:streamGeometryContext,Point,Top,实践,GroupBox,new,rect,Avalonia
From: https://blog.csdn.net/wsadcg/article/details/140626316