Click here to Skip to main content
15,881,380 members
Articles / Desktop Programming / WPF
Article

How to Build a Custom Formatted Label with WPF

Rate me:
Please Sign up or sign in to vote.
4.50/5 (4 votes)
1 Nov 2007CPOL1 min read 35K   331   19   1
This article explains how to provide a custom gauge formatter for WPF TextBlocks, Label or any other controls

Introduction

Creating a custom control in Windows Forms by using OwnerDraw in GDI+ is very hard. WPF reveals a new way to build rich client applications with only some lines of code. Here is an example showing the creation of a custom control that provides Label and Gauge functionality.

Background

First of all, let's understand what we want to archive? We want our gradientbrush to change its end point, according to a relative value passed to the item. In the GDI+ world, we have to perform a dozen calculations and draw rectangles with custom effect to provide such a view. Within WPF, all we need is one brush and one converter. Let's see.

Using the Code

In order to visualize the data, we have to write a custom DataTemplate:

XML
<DataTemplate x:Key="template"> 
      <TextBlock Text="{Binding}" > 
        <TextBlock.Background> 
          <LinearGradientBrush EndPoint="{Binding Converter={StaticResource converter},
                 ConverterParameter=1000}" StartPoint="0,0.5"> 
            <GradientStop Color="#FF7CA0CF" Offset="0"/> 
            <GradientStop Color="#FF7CA0CF" Offset="0.8"/> 
            <GradientStop Color="#FFFFFFFF" Offset="1"/> 
          </LinearGradientBrush> 
        </TextBlock.Background> 
      </TextBlock> 
 </DataTemplate>

Now, we have to create a converter to translate source value into screen points, which will be used within the brush to show the relative value.

C#
class DataConverter:IValueConverter 
{ 
public object Convert(object value, Type targetType, 
    object parameter, System.Globalization.CultureInfo culture) 
{ 
int val = (int)value; 
int max = int.Parse(parameter.ToString()); 
return new Point(val == 0 ? 0 : ((double)val / (double)max), 0.5); 
}

The last action is that we take each control and "tell" the WPF layout engine to stretch it according to its ancestor's size.

XML
<TextBlock Text="{Binding}" 
Margin="5,5,5,5" TextAlignment="Right" Padding="0,0,20,0" 
Width="{Binding RelativeSource={RelativeSource AncestorType={x:Type ListBox}}, 
Path=ActualWidth}"> 

What did we actually do here? Just binded Width value of each TextBlock control within DataTemplate to the size of its ancestor (in this case ListBox) to stretch it to fill the available space.

History

  • 1st November, 2007: Initial post

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Architect Better Place
Israel Israel
Hello! My name is Tamir Khason, and I am software architect, project manager, system analyst and [of course] programmer. In addition to writing big amount of documentation, I also write code, a lot of code. I used to work as a freelance architect, project manager, trainer, and consultant here, in Israel, but recently join the company with extremely persuasive idea - to make a world better place. I have very pretty wife and 3 charming kids, but unfortunately almost no time for them.

To be updated within articles, I publishing, visit my blog or subscribe RSS feed. Also you can follow me on Twitter to be up to date about my everyday life.

Comments and Discussions

 
GeneralMy vote of 5 Pin
srilekhamenon30-Oct-18 1:50
professionalsrilekhamenon30-Oct-18 1:50 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.