众所周知,诸如Border、Rectangle等元素,是具有边框的。但在WPF和Avalonia中,边框的渲染机制有所不同。
如下代码,Border的边框和背景色均为黑色,并且将透明度设为0.5:
<Border Width="100" Height="40" BorderBrush="Black" BorderThickness="5" Opacity="0.5" Background="Black" CornerRadius="5"/>
此代码在两种框架下的表现如图:
1)WPF中Border在设置透明度的情况下,颜色是整体变化无差异的,看似效果很好。但仔细观察不难发现,圆角区域边框与内容之间是有空隙的(放大后观看更为明显)。
这是由于对边缘圆角进行了平滑处理导致的,通过设置RenderOptions.EdgeMode="Aliased"可以解决缝隙问题,但圆角部分会呈现锯齿,可谓二者不可兼得。
2)Avalonia中的Border边框和内容有部分重叠,如此一来虽消除了圆角缝隙,但也导致交叠区不透明度加深,出现图中的深色内边框效果,影响观感。
总之,两种框架对边框的处理均有利有弊,在实际开发过程中只能避开缺陷。如尽量避免边框和背景色同时渲染;如要同时渲染,在Avalonia中还应注意透明度的问题。
后来笔者通过阅读Avalonia源码发现,Border在计算填充背景色区域的矩形范围时,新增了三种计算方式,依靠BackgroundSizing枚举值来设置:
/// <summary>
/// Defines how a background is drawn relative to its border.
/// </summary>
public enum BackgroundSizing
{
/// <summary>
/// The background is drawn up to the inside edge of the border.
/// </summary>
/// <remarks>
/// The background will never be drawn under the border itself and will not be visible
/// underneath the border regardless of border transparency.
/// </remarks>
InnerBorderEdge = 0,
/// <summary>
/// The background is drawn completely to the outside edge of the border.
/// </summary>
/// <remarks>
/// The background will be visible underneath the border if the border has transparency.
/// </remarks>
OuterBorderEdge = 1,
/// <summary>
/// The background is drawn to the midpoint (center) of the border.
/// </summary>
/// <remarks>
/// The background will be visible underneath half of the border if the border has transparency.
/// For this reason it is not recommended to use <see cref="CenterBorder"/> if transparency is involved.
/// <br/><br/>
/// This value does not exist in other XAML frameworks and only exists in Avalonia for backwards compatibility
/// with legacy code. Before <see cref="BackgroundSizing"/> was added, Avalonia would always render using this
/// value (Skia's default).
/// </remarks>
CenterBorder = 2,
}
而Border默认设置的是BackgroundSizing=CenterBorder,也就是当前版本的效果,所以边框会与背景有部分重叠。目前这一版本代码还未发布,有兴趣的朋友可以研究源码自己实现一下Border的绘制。
Avalonia 11.1.0 版本后,已经将BackgroundSizing属性加入到Border中,这样就可以根据需要决定背景色的绘制方式了。