WPF附加依赖属性实现自适应字体大小(根据屏幕分辨率变化)
前言
近来有个需求,软件需要动态适配屏幕分辨率,为了保证整体界面的一致性,字体的大小需要根据不同的屏幕分辨率自适应大小。此篇只为给提供一个处理的方法,直接使用也可以,不过还需要有一些改动。此处只做一个简单版本的记录。
使用方法
- 初始化
RelativeSizeAttach.Init(1920,1080)
(用于计算屏幕的宽高转换比) - 引入命名空间
xmlns:前缀="clr-namespace:命名空间名称;assembly:程序集名称"
- 在需要使用自适应附加属性的xaml标签内进行属性值设置。
例如:前缀:RelativeSizeAttach.FontSize="16"
;
代码
public class RelativeSizeAttach
{
#region 宽高
public static readonly DependencyProperty WidthProperty
= DependencyProperty.RegisterAttached("Width", typeof(double), typeof(RelativeSizeAttach), new FrameworkPropertyMetadata(0.0, WidthPropertyChangedCallback));
public static void SetWidth(DependencyObject element, double value) => element.SetCurrentValue(WidthProperty, value);
public static double GetWidth(DependencyObject element) => (double)element.GetValue(WidthProperty);
private static void WidthPropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (d is ColumnDefinition column)
{
column.SetCurrentValue(ColumnDefinition.WidthProperty, new GridLength(WidthRateConverter((double)e.NewValue)));
}
else if (d is FrameworkElement element)
{
element.SetCurrentValue(FrameworkElement.WidthProperty, WidthRateConverter((double)e.NewValue));
}
}
public static readonly DependencyProperty HeightProperty
= DependencyProperty.RegisterAttached("Height", typeof(double), typeof(RelativeSizeAttach), new FrameworkPropertyMetadata(0.0, HeightPropertyChangedCallback));
public static void SetHeight(DependencyObject element, double value) => element.SetCurrentValue(HeightProperty, value);
public static double GetHeight(DependencyObject element) => (double)element.GetValue(HeightProperty);
private static void HeightPropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (d is RowDefinition row)
{
row.SetCurrentValue(RowDefinition.HeightProperty, new GridLength(HeightRateConverter((double)e.NewValue)));
}
else if (d is FrameworkElement element)
{
element.SetCurrentValue(FrameworkElement.HeightProperty, HeightRateConverter((double)e.NewValue));
}
}
#endregion
#region 字体大小
public static readonly DependencyProperty FontSizeProperty
= DependencyProperty.RegisterAttached("FontSize", typeof(double), typeof(RelativeSizeAttach), new FrameworkPropertyMetadata(0.0, FontSizePropertyChangedCallback));
public static void SetFontSize(DependencyObject element, double value) => element.SetCurrentValue(FontSizeProperty, value);
public static double GetFontSize(DependencyObject element) => (double)element.GetValue(FontSizeProperty);
private static void FontSizePropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (d is TextBlock txtBlock)
{
txtBlock.SetCurrentValue(TextBlock.FontSizeProperty, WidthRateConverter((double)e.NewValue));
}
}
#endregion
#region 行高
public static readonly DependencyProperty LineHeightProperty
= DependencyProperty.RegisterAttached("LineHeight", typeof(double), typeof(RelativeSizeAttach), new FrameworkPropertyMetadata(0.0, LineHeightPropertyChangedCallback));
public static void SetLineHeight(DependencyObject element, double value) => element.SetCurrentValue(LineHeightProperty, value);
public static double GetLineHeight(DependencyObject element) => (double)element.GetValue(LineHeightProperty);
private static void LineHeightPropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (d is TextBlock txtBlock)
{
txtBlock.SetCurrentValue(TextBlock.LineHeightProperty, WidthRateConverter((double)e.NewValue));
}
}
#endregion
#region 边距
public static readonly DependencyProperty MarginProperty
= DependencyProperty.RegisterAttached("Margin", typeof(Thickness), typeof(RelativeSizeAttach), new FrameworkPropertyMetadata(new Thickness(0), MarginPropertyChangedCallback));
public static void SetMargin(DependencyObject element, Thickness value) => element.SetCurrentValue(MarginProperty, value);
public static Thickness GetMargin(DependencyObject element) => (Thickness)element.GetValue(MarginProperty);
private static void MarginPropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (d is FrameworkElement element)
{
element.SetCurrentValue(FrameworkElement.MarginProperty, ThicknessRateConverter((Thickness)e.NewValue));
}
}
public static readonly DependencyProperty PaddingProperty
= DependencyProperty.RegisterAttached("Padding", typeof(Thickness), typeof(RelativeSizeAttach), new FrameworkPropertyMetadata(new Thickness(0), PaddingPropertyChangedCallback));
public static void SetPadding(DependencyObject element, Thickness value) => element.SetCurrentValue(PaddingProperty, value);
public static Thickness GetPadding(DependencyObject element) => (Thickness)element.GetValue(PaddingProperty);
private static void PaddingPropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (d is Border border)
{
border.SetCurrentValue(Border.PaddingProperty, ThicknessRateConverter((Thickness)e.NewValue));
}
}
#endregion
#region 数据处理
private static double _widthRate = 1;
private static double _heightRate = 1;
/// <summary>
/// 初始化方法
/// </summary>
/// <param name="deviceWidth">设备宽度</param>
/// <param name="deviceHeight">设备高度</param>
/// <param name="designWidth">设计图宽度</param>
/// <param name="designHeight">设计图高度</param>
public static void Init(double deviceWidth, double deviceHeight, double designWidth = 1024, double designHeight = 768)
{
_widthRate = deviceWidth / designWidth;
_heightRate = deviceHeight / designHeight;
}
private static double WidthRateConverter(double value) => value * _widthRate;
private static double HeightRateConverter(double value) => value * _heightRate;
private static Thickness ThicknessRateConverter(Thickness value)
{
value.Left *= _widthRate;
value.Top *= _heightRate;
value.Right *= _widthRate;
value.Bottom *= _heightRate;
return value;
}
#endregion
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南