I would like to make a CustomControl Label
, which could have a property called Percentage and the background would be filled according to that percentage. example: label.Percentage = 70
then the background color would fill only 70% of the label size.
I've created a Custom Control
:
<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">
<Border x:Name="backgroundBorder" Background="Transparent">
<TextBlock x:Name="textBlock" Text="Label Text" HorizontalAlignment="Center" VerticalAlignment="Center" Foreground="White"/>
</Border>
I set the properties of the PercentageLabel like this:
public partial class PercentageLabel : UserControl
{
public PercentageLabel()
{
InitializeComponent();
}
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;
// Ensure the percentage is within the valid range
newPercentage = Math.Min(100, Math.Max(0, newPercentage));
// Calculate the width of the filled and unfilled parts of the background
var fillWidth = label.ActualWidth * (newPercentage / 100);
// Update the background color (FillColor) and the filled background width
label.backgroundBorder.Background = label.FillColor;
label.backgroundBorder.Width = fillWidth;
label.backgroundBorder.HorizontalAlignment= HorizontalAlignment.Left;
}
}
And finnaly I add the custom control in a Window.
<local:PercentageLabel Grid.Row="0" Grid.Column="0" Percentage="70" FillColor="Green"/>
Problems:
You could use Grid and overlapping Controls, textBlockBar is your percentage bar that will fill whatever you need
textBlockBG is the background box that will have your text and background
In your user control:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="50"></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Border x:Name="backgroundBorder1" Background="Transparent" Grid.Row="0" Grid.Column="0">
<TextBlock x:Name="textBlockBar" HorizontalAlignment="Center" VerticalAlignment="Center" Foreground="White" Opacity="0.1" Text="">
</TextBlock>
</Border>
<Border x:Name="backgroundBorder2" Background="Transparent" Grid.Row="0" Grid.Column="0">
<TextBlock x:Name="textBlockBG" HorizontalAlignment="Center" VerticalAlignment="Center" Foreground="White" Opacity="1" Text="">
</TextBlock>
</Border>
</Grid>
Update your Usercontrol class accordingly:
public partial class PercentageLabel : UserControl
{
public PercentageLabel()
{
InitializeComponent();
}
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 string Text
{
get
{
return this.textBlockBG.Text;
}
set
{
this.textBlockBG.Text = value;
}
}
public Brush FillColor
{
get { return (Brush)GetValue(FillColorProperty); }
set { SetValue(FillColorProperty, value); }
}
public Brush BackColor
{
get { return this.Background; }
set { this.Background = value; }
}
public Brush TextColor
{
get { return this.textBlockBG.Foreground; }
set { this.textBlockBG.Foreground = value; }
}
private static void OnPercentageChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var label = (PercentageLabel)d;
var newPercentage = (double)e.NewValue;
// Ensure the percentage is within the valid range
newPercentage = Math.Min(100, Math.Max(0, newPercentage));
// Calculate the width of the filled and unfilled parts of the background
var fillWidth = label.ActualWidth * (newPercentage / 100);
// Update the background color (FillColor) and the filled background width
label.backgroundBorder1.Background = label.FillColor;
label.backgroundBorder1.Width = fillWidth;
label.backgroundBorder1.HorizontalAlignment = HorizontalAlignment.Left;
}
Then in your Window, just do this
<local:PercentageLabel x:Name="pLabel1" Grid.Row="0" Grid.Column="0" Percentage="70" FillColor="Blue" BackColor="Orange" TextColor="Yellow"/>
There is an issue though that you need to handle when you resize your window the % does not follow the window size, I will leave it to you to fix it :)