Change FontSize with ElementBinding

Jakob Nielsen says: “Let users control font size”. Unfortunately in Silverlight the nice features of the WPF FlowDocument control are not available (yet). You cannot use the automatic font size feature of that control in a Silverlight app. But in Silverlight 3 ElementBinding enables you to bind a value to the FontSize attribute of a TextBlock. Using a Converter with a ConverterParameter, dynamic font size becomes available:

Click for working version...

The trick is to use TextBlock controls for your text and set it’s properties in a Style, like you would normally do. This time, leave the FontSize attribute out.

<Style x:Key=”Body” TargetType=”TextBlock”>
    <Setter Property=”FontFamily” Value=”Trebuchet MS” />
    <Setter Property=”TextWrapping” Value=”Wrap” />
</Style>
<Style x:Key=”Header” TargetType=”TextBlock” BasedOn=”{StaticResource Body}”>
    <Setter Property=”FontWeight” Value=”Bold” />
</Style>
<Style x:Key=”Caption” TargetType=”TextBlock” BasedOn=”{StaticResource Body}”>
    <Setter Property=”FontStyle” Value=”Italic” />
    <Setter Property=”Foreground” Value=”Gray” />
</Style>

Create TextBlocks with these Styles and Text, but set the FontSize attribute to an ElementBinding with the Value of a small Slider.

<TextBlock x:Name=”txtHeader1″ Style=”{StaticResource Header}”  FontSize=”{Binding Value, ElementName=Slider, Converter={StaticResource FontSizeConverter}, ConverterParameter=H1}” Text=”Header 1″/>

<Slider x:Name=”Slider” Value=”10″ SmallChange=”1″ LargeChange=”12″ Minimum=”6″ Maximum=”72″ Width=”100″ />

The converter will set the FontSize for you. The ConverterParameter has string values from “H1” to “H7”, like you would use in HTML. You can set this to any string you like, but these seem to make sense…

The converter looks like this:

using System;
using System.Windows.Data;

namespace Converters
{
    public class FontSizeConverter : IValueConverter  
    {
        public object Convert(object value, Type targetType, object parameter,
System.Globalization.CultureInfo culture)  
        {
            double v = (double)value;

            if (parameter != null)
            {
                string fontSizeString = parameter.ToString();
                if (!string.IsNullOrEmpty(fontSizeString))
                {
                    switch(fontSizeString)
                    {
                        case “H1” :
                            value = 2.4 * v;
                        break;
                        case “H2” :
                            value = 1.8 * v;
                        break;
                        case “H3” :
                            value = 1.4 * v;
                        break;
                        case “H4” :
                            value = 1.2 * v;
                        break;
                        case “H5” :
                            value = 1 * v;
                        break;
                        case “H6” :
                            value = .8 * v;
                        break;
                        case “H7″ :
                            value = .6 * v;
                        break;
                    }
                }
            }
            value = System.Convert.ToInt32(value); // we need an integer, not double…
            return value.ToString(); // …but as a string
        }
    }
}

As you can see the value is updated with different multipliers, depending on the header parameter you pass in. H5 is the basic text size, used by the Body Text, so its multiplier is 1. You can play with these multipliers if you want a different effect.

Add the namespace to your XAML file and put the converter as a resource at the top of the file…

<UserControl x:Class=”ControlFontSize.MainPage”
    xmlns:cvs=”clr-namespace:Converters”>
    <UserControl.Resources>
        <cvs:FontSizeConverter x:Key=”FontSizeConverter” />
    </UserControl.Resources>

… and you’re good to go. Let users control text size!

Working code is on my SkyDrive… Njoy!

SketchFlow Behavior CheatSheets

Personally, I think that not enough Behaviors for Blend and SketchFlow are available, but luckily Christian Schormann recently presented some SketchFlow Behaviors that make Conditional Navigation and Global States possible in SketchFlow prototypes. For my workshop on SketchFlow for PICNIC09, I created two CheatSheets in SketchFlow, because working with Behaviors is too complex to explain quickly in a workshop. Since the workshops are done, I’d like to share these CheatSheets with you so you can learn quickly how to use the behaviors Christian created.

ConditionalNavigationCheatSheet GlobalStateCheatSheet

The Conditional Navigation behaviors enables you to navigate to a different screen based on a TargetScreen variable that is set using events in the interface.

The Global State behavior is similar but makes it possible to navigate to a screen that shows a particular state, depending on a GlobalState variable, setting the state.

If you can’t reach a result using these cheatsheet, please read the explanation from Christian on his blog. Check out the CheatSheets and enjoy using SketchFlow!