[.NET/WPF] Set rounded corners for buttons, and any other controls that contain borders

In WPF, the button contains a "border", and it is often necessary to set the rounded corners of the button, but the button does not provide a property to set the rounded corners of the border.

The following takes the button as an example to list several commonly used methods of setting rounded corners.

via additional properties

Define an additional attribute, and then use it directly and conveniently in various places. The following is the actual usage method:

<Button utils.BorderUtils.CornerRadius="3"/>

Next is the specific implementation code, first of all some tool methods:

using System.Windows.Media;

namespace System.Windows
{
    
    
    public static class CommonUtils
    {
    
    
        public static void RunOnFirstLoaded(this FrameworkElement element, EventHandler handler)
        {
    
    
            void Once(object? sender, RoutedEventArgs e)
            {
    
    
                element.Loaded -= Once;
                handler.Invoke(sender, e);
            }

            if (element.IsLoaded)
                handler.Invoke(element, EventArgs.Empty);
            else
                element.Loaded += Once;
        }

        public static TElement? GetElementFromVisualTree<TElement>(this FrameworkElement control) where TElement : FrameworkElement
        {
    
    
            if (control is TElement ele)
                return ele;

            int childrenCount = VisualTreeHelper.GetChildrenCount(control);
            for (int i = 0; i < childrenCount; i++)
            {
    
    
                DependencyObject child = VisualTreeHelper.GetChild(control, i);
                if (child is TElement eleChild)
                    return eleChild;
            }

            return null;
        }
    }
}

Then there is the BorderUtils class, where the CornerRadius additional property is defined:

using System;
using System.Windows.Controls;
using System.Windows.Media;

namespace System.Windows
{
    
    
    public static class BorderUtils
    {
    
    
        [AttachedPropertyBrowsableForType(typeof(FrameworkElement))]
        public static CornerRadius GetCornerRadius(DependencyObject obj)
        {
    
    
            return (CornerRadius)obj.GetValue(CornerRadiusProperty);
        }

        public static void SetCornerRadius(DependencyObject obj, CornerRadius value)
        {
    
    
            obj.SetValue(CornerRadiusProperty, value);
        }

        // Using a DependencyProperty as the backing store for CornerRadius.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty CornerRadiusProperty =
            DependencyProperty.RegisterAttached("CornerRadius", typeof(CornerRadius), typeof(BorderUtils), new PropertyMetadata(new CornerRadius(), CornerRadiusChanged));

        private static void CornerRadiusChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
    
    
            if (d is not FrameworkElement ele)
                return;

            ele.RunOnFirstLoaded((s, _e) =>
            {
    
    
                if (CommonUtils.GetElementFromVisualTree<Border>(ele) is not Border border)
                    return;

                border.CornerRadius = (CornerRadius)e.NewValue;
            });
        }
    }
}

through resources

Add a Border style resource directly under the Button node, and then the Border in the Button will apply this style.

<Button>
  <Button.Resources>
    <Style TargetType="Border">
      <Setter Property="CornerRadius" Value="3" />
    </Style>
  </Button.Resources>
</Button>

via template

A very troublesome way, not recommended

<Button>
  <Button.Template>
    <ControlTemplate TargetType="{x:Type Button}" >
      <Border BorderBrush="{TemplateBinding Control.BorderBrush}" BorderThickness="1" CornerRadius="7,7,7,7">
        <Border.Background>#FFDDDDDD</Border.Background>
        <ContentPresenter Content="{TemplateBinding ContentControl.Content}" HorizontalAlignment="Center" VerticalAlignment="Center" ></ContentPresenter>
      </Border>
    </ControlTemplate>
  </Button.Template>
</Button>

Guess you like

Origin blog.csdn.net/m0_46555380/article/details/130777656