You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现带百分比填充背景的WPF自定义Label控件?

解决方案:修复WPF PercentageLabel自定义控件的两个问题

问题根源分析

  1. 编辑Content后背景消失:UserControl的Content属性会直接替换其内部默认布局元素,设置Content时原有的backgroundBorder和textBlock会被移除,导致背景丢失。
  2. 文本受百分比影响:TextBlock嵌套在背景Border内部,当Border宽度随百分比缩小时,TextBlock的可用空间被限制,导致文字显示不全或不可见。

修复后的完整实现

1. XAML布局修改

使用Grid分层布局,将背景层与文本层分离,确保文本层不受背景宽度影响:

<UserControl x:Class="NameSpace.PercentageLabel"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:NameSpace"                
             Background="Transparent">
    <!-- Grid实现分层:背景层在下,文本层在上 -->
    <Grid>
        <!-- 背景填充层:仅根据百分比调整宽度,左对齐 -->
        <Border x:Name="backgroundBorder" 
                Background="Transparent"
                HorizontalAlignment="Left"/>
        <!-- 文本层:占满整个控件空间,居中显示,不受背景宽度限制 -->
        <TextBlock x:Name="textBlock" 
                   Text="{Binding RelativeSource={RelativeSource AncestorType=local:PercentageLabel}, Path=Text}"
                   HorizontalAlignment="Center" 
                   VerticalAlignment="Center" 
                   Foreground="White"/>
    </Grid>
</UserControl>

2. C#代码修改

新增Text依赖属性替代Content,添加尺寸变化监听,优化背景宽度更新逻辑:

public partial class PercentageLabel : UserControl
{
    public PercentageLabel()
    {
        InitializeComponent();
        // 监听控件尺寸变化,窗口resize时自动更新背景宽度
        SizeChanged += PercentageLabel_SizeChanged;
    }

    private void PercentageLabel_SizeChanged(object sender, SizeChangedEventArgs e)
    {
        UpdateBackgroundWidth(Percentage);
    }

    // 自定义Text依赖属性,用于设置标签文本
    public static readonly DependencyProperty TextProperty =
        DependencyProperty.Register("Text", typeof(string), typeof(PercentageLabel), new PropertyMetadata("Label Text"));

    public string Text
    {
        get { return (string)GetValue(TextProperty); }
        set { SetValue(TextProperty, value); }
    }

    public static readonly DependencyProperty PercentageProperty =
        DependencyProperty.Register("Percentage", typeof(double), typeof(PercentageLabel), new PropertyMetadata(0.0, OnPercentageChanged));

    public double Percentage
    {
        get { return (double)GetValue(PercentageProperty); }
        set { SetValue(PercentageProperty, value); }
    }

    public static readonly DependencyProperty FillColorProperty =
        DependencyProperty.Register("FillColor", typeof(Brush), typeof(PercentageLabel), new PropertyMetadata(Brushes.Black));

    public Brush FillColor
    {
        get { return (Brush)GetValue(FillColorProperty); }
        set { SetValue(FillColorProperty, value); }
    }

    private static void OnPercentageChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var label = (PercentageLabel)d;
        var newPercentage = (double)e.NewValue;
        label.UpdateBackgroundWidth(newPercentage);
    }

    // 复用的背景宽度更新逻辑
    private void UpdateBackgroundWidth(double percentage)
    {
        // 确保百分比在0-100的有效范围内
        var validPercentage = Math.Min(100, Math.Max(0, percentage));
        // 计算背景填充宽度
        var fillWidth = ActualWidth * (validPercentage / 100);
        // 更新背景样式
        backgroundBorder.Background = FillColor;
        backgroundBorder.Width = fillWidth;
    }
}

3. 控件使用示例

<local:PercentageLabel Grid.Row="0" Grid.Column="0" 
                       Percentage="70" 
                       FillColor="Green"
                       Text="自定义标签内容"/>

关键修改点说明

  • 替换Content为自定义Text属性:避免设置文本时覆盖内部布局结构,保证背景层始终存在。
  • 分层布局:通过Grid将背景层与文本层分离,文本层占满整个控件空间,不受背景宽度限制。
  • 尺寸变化监听:窗口resize时自动重新计算背景宽度,保证百分比显示的准确性。
  • 逻辑复用:将背景宽度更新逻辑提取为独立方法,减少重复代码。

内容的提问来源于stack exchange,提问作者DarkWarrior

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 01:42:49