Sunday, October 14, 2007

Formatting templates and one small tip

From internal discussion list:
Are there any samples around doing this kind of formatting with WPF?


My response: This should be very easy to do with value converter for Background brush of Item template.

How to do it?

First of all, let's understand what we want to archive? We want our gradientbrush to change it's end point, according to relative value passed to the item. So, let's do it

<DataTemplate x:Key="template">
      <TextBlock Text="{Binding}" >
          <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"/>

In the code of converter we'll just translate values, according the max value, passed as parameter.

class DataConverter:IValueConverter
        #region IValueConverter Members

        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);

Very good. Compile and run. We get wrong result. Why? Due to fact, that TextBlock control does not resizes and stretches, according it's parent width. We can do it hardcoded for sure, but we want it automatically. Binding will help us another time. But this time, it's relative binding to ancestor's value.

<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}">

That's all. We got the behavior, we looked for. See yourself.


Source code for this article.

No comments: