XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet

XFEToolBox

【WPF】XFE工具箱

公开
关注 0 Fork 0 Star 0
UTF-8
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;

namespace XFEToolBox.WpfCore.Controls;

/// <summary>
/// 会按照 CornerRadius 真正裁剪子内容的 Border。
/// WPF 原生 Border 只绘制圆角,不会裁剪内部元素。
/// </summary>
public sealed class RoundedClipBorder : Border
{
    protected override void OnRenderSizeChanged(SizeChangedInfo sizeInfo)
    {
        base.OnRenderSizeChanged(sizeInfo);
        UpdateClip();
    }

    protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
    {
        base.OnPropertyChanged(e);
        if (e.Property == CornerRadiusProperty)
            UpdateClip();
    }

    private void UpdateClip()
    {
        if (ActualWidth <= 0 || ActualHeight <= 0)
        {
            Clip = null;
            return;
        }

        var maximumRadius = Math.Min(ActualWidth, ActualHeight) / 2;
        var topLeft = Math.Min(CornerRadius.TopLeft, maximumRadius);
        var topRight = Math.Min(CornerRadius.TopRight, maximumRadius);
        var bottomRight = Math.Min(CornerRadius.BottomRight, maximumRadius);
        var bottomLeft = Math.Min(CornerRadius.BottomLeft, maximumRadius);

        var geometry = new StreamGeometry();
        using (var context = geometry.Open())
        {
            context.BeginFigure(new Point(topLeft, 0), true, true);
            context.LineTo(new Point(ActualWidth - topRight, 0), true, false);
            context.QuadraticBezierTo(new Point(ActualWidth, 0), new Point(ActualWidth, topRight), true, false);
            context.LineTo(new Point(ActualWidth, ActualHeight - bottomRight), true, false);
            context.QuadraticBezierTo(new Point(ActualWidth, ActualHeight), new Point(ActualWidth - bottomRight, ActualHeight), true, false);
            context.LineTo(new Point(bottomLeft, ActualHeight), true, false);
            context.QuadraticBezierTo(new Point(0, ActualHeight), new Point(0, ActualHeight - bottomLeft), true, false);
            context.LineTo(new Point(0, topLeft), true, false);
            context.QuadraticBezierTo(new Point(0, 0), new Point(topLeft, 0), true, false);
        }
        geometry.Freeze();
        Clip = geometry;
    }
}