6

I am creating a custom WPF control that let's say for simplicity sake has a vertical stack panel with a "title" TextBlock, followed by a ContentPresenter. I want the font size for the "title" to be 5 Points LARGER than the size used in the content, which is inherited by whatever container the user places this control in.

How can I specify a font size in the control template for the header element using a relative value without exposing a property like "TitleFontSize" to the user? I want do "add 5".

I tried using a ScaleTransform on the header text block with mixed results (the text block scaled fine but the orientation was modified - I had the text right-justified and it moved "off the control" area when scaled). Also, I am not sure if scale transform would be approprite here.

Bill
  • 2,381
  • 4
  • 21
  • 24

2 Answers2

15

A more generic way

Value converter

public class MathConverter : IValueConverter
{
    public object Convert( object value, Type targetType, object parameter, CultureInfo culture )
    {
        return (double)value + double.Parse( parameter.ToString() );
    }

    public object ConvertBack( object value, Type targetType, object parameter, CultureInfo culture )
    {
        return null;
    }
}

Converter Resource

<my:MathConverter x:Key="MathConverter" />

XAML

<TextBlock FontSize="{Binding
                     RelativeSource={RelativeSource AncestorType={x:Type Window}},
                     Path=FontSize,
                     Converter={StaticResource MathConverter},
                     ConverterParameter=2}" />
Thomas
  • 1,295
  • 14
  • 12
  • 4
    I'd actually go a small step further and make it use multiplication against a scale (either 0.0-1.0 or 0-100%). That way it's a 'true' relative sizing. AFter all, if the font size is 20 and you're subtracting 10, that yields 10 or 50% size. But if you're at 40 and subtract 10, you're only at 30 or 75% size. Using a scaling value you could always maintain size proportions. – Mark A. Donohoe Dec 11 '11 at 01:38
  • 8
    So much code for such a trivial effect... Is something wrong with the WPF in general? – Califf Dec 07 '12 at 15:28
5

I did it with an IValueConverter as follows:

Created a class FontSizeConverter that derives from IValueConverter. The Convert method adds 10 to the value, and the ConvertBack method subtracts 10.

public class FontSizeConverter : IValueConverter
{

    #region IValueConverter Members

    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return (double)value + 12.0;
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return (double)value - 12.0;
    }

    #endregion
}

Next, I declaried an instance of this class in the XAML template for the control:

<Style.Resources>
        <local:FontSizeConverter x:Key="fontSizeConverter"/>
</Style.Resources>

And Finnaly, the FontSize binding uses this converter applied to the inherited FontSize property:

<TextBlock FontSize="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=FontSize, Converter={StaticResource fontSizeConverter}}" 
                                   Grid.Row="0" Text="{Binding RelativeSource={RelativeSource TemplatedParent}, 
                                   Path=Date.Day}" HorizontalAlignment="Right" VerticalAlignment="Top" Padding="2" Margin="2" >
 </TextBlock>

This works. But I still do not know if this is the correct answer. Let me know if there is a better way, or if this is appropriate.

Bill
  • 2,381
  • 4
  • 21
  • 24
  • Looks good to me, the only change I would make is to pass the value that's being added to the FontSize through the ConverterParameter, rather than hard coding it in the converter. – Ian Oakes Nov 23 '08 at 00:25
  • As Ian said, I'd add a ConverterParameter but otherwise that looks good. – Donnelle Nov 23 '08 at 22:11
  • I tried this solution and it did absolutely nothing. The value converter never gets called. – cppguy Nov 13 '17 at 22:16