WPF(自适应圆)
在WPF中可以实现椭圆,利用Ellipse或者Border。但是要实现圆,就必须设定固定的长宽,然后根据长宽设置对应的倒角才可以实现圆。如果这样设计,就固定了长宽,不能根据界面自适应调整。所以我们可以根据绑定和转换器将实际的长宽转换为对应的倒角。
using System;
using System.Globalization;
using System.Windows.Data;
[ValueConversion(typeof(double), typeof(double[]))]
public class RoundMathConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
if (values.Length < 2)
{
throw new NotImplementedException();
}
double.TryParse(values[0].ToString(), out double d1);
double.TryParse(values[1].ToString(), out double d2);
if (d1 * d2 == 0)
{
return double.NaN;
}
return Math.Min(d1, d2);
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
[ValueConversion(typeof(System.Windows.CornerRadius), typeof(double[]))]
public class RoundRadiusConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
if (values.Length < 2)
{
throw new NotImplementedException();
}
double.TryParse(values[0].ToString(), out double d1);
double.TryParse(values[1].ToString(), out double d2);
double ratio = 1;
if (values.Length >= 3)
{
double.TryParse(values[2].ToString(), out ratio);
}
return new System.Windows.CornerRadius(Math.Min(d1, d2) * ratio / 2);
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
1.椭圆
using System.Windows;
using System.Windows.Controls;
/// <summary>
/// EllipseBorder.xaml 的交互逻辑
/// </summary>
public partial class EllipseBorder : Border
{
public static readonly DependencyProperty RadiusRatioProperty =
DependencyProperty.Register(nameof(RadiusRatio), typeof(float), typeof(EllipseBorder), new FrameworkPropertyMetadata(1f));
public float RadiusRatio
{
get { return (float)GetValue(RadiusRatioProperty); }
set { SetValue(RadiusRatioProperty, value); }
}
public EllipseBorder()
{
InitializeComponent();
}
}
<Border x:Class="WpfApp360.CustomControl.EllipseBorder"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApp360.Converter"
xmlns:con="clr-namespace:WpfApp360.Converter"
d:DesignHeight="450" d:DesignWidth="800" mc:Ignorable="d">
<Border.CornerRadius>
<MultiBinding>
<MultiBinding.Converter>
<con:RoundRadiusConverter />
</MultiBinding.Converter>
<Binding Path="ActualWidth" RelativeSource="{RelativeSource Self}" />
<Binding Path="ActualHeight" RelativeSource="{RelativeSource Self}" />
<Binding Path="RadiusRatio" RelativeSource="{RelativeSource Self}" />
</MultiBinding>
</Border.CornerRadius>
</Border>
可通过设置RadiusRatio来控制倒角的比例。
2.圆
由于圆需要根据ActualHeight和ActualWidth 来设置元素的Width和Height,但是这两者之间会互相影响,所以我们不能和椭圆一样来定义一个Border。下面我们设计一个圆形Button,在Button模板中定义一个Border。
<Button x:Class="WpfApp360.CustomControl.RoundButton"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:con="clr-namespace:WpfApp360.Converter"
d:DesignHeight="400" d:DesignWidth="400" mc:Ignorable="d">
<Button.Template>
<ControlTemplate TargetType="Button">
<Border Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}">
<Border.CornerRadius>
<MultiBinding>
<MultiBinding.Converter>
<con:RoundRadiusConverter />
</MultiBinding.Converter>
<Binding Path="ActualWidth" RelativeSource="{RelativeSource TemplatedParent}" />
<Binding Path="ActualHeight" RelativeSource="{RelativeSource TemplatedParent}" />
</MultiBinding>
</Border.CornerRadius>
<Border.Width>
<MultiBinding>
<MultiBinding.Converter>
<con:RoundMathConverter />
</MultiBinding.Converter>
<Binding Path="ActualWidth" RelativeSource="{RelativeSource TemplatedParent}" />
<Binding Path="ActualHeight" RelativeSource="{RelativeSource TemplatedParent}" />
</MultiBinding>
</Border.Width>
<Border.Height>
<MultiBinding>
<MultiBinding.Converter>
<con:RoundMathConverter />
</MultiBinding.Converter>
<Binding Path="ActualWidth" RelativeSource="{RelativeSource TemplatedParent}" />
<Binding Path="ActualHeight" RelativeSource="{RelativeSource TemplatedParent}" />
</MultiBinding>
</Border.Height>
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
</Border>
</ControlTemplate>
</Button.Template>
</Button>
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现