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
:
<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.
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.
<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