2 Comments

Toggle the Visibility of a Text Run in WPF

I ran into a situation the other day where I had to turn on/off the visibility of a text run in WPF, and I discovered that text runs do not have a visibility property. 

Whenever I run into a situation where I need to add functionality to a control, I always turn to attached properties as my go-to tool. Here is a quick and easy way to add the visibility functionality using an attached property.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
public static class RunVisibility
{
    public static readonly DependencyProperty VisibleProperty =
        DependencyProperty.RegisterAttached("Visible", typeof(bool), typeof(RunVisibility),
            new FrameworkPropertyMetadata(true, new PropertyChangedCallback(OnVisibilityChanged)));
 
    public static bool GetVisible(Run d)
    {
        return (bool)d.GetValue(VisibleProperty);
    }
 
    public static void SetVisible(Run d, bool value)
    {
        d.SetValue(VisibleProperty, value);
    }
 
    private static void OnVisibilityChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        if (d is Run)
        {
            var run = (d as Run);
            if ((bool)e.NewValue == true)
            {
                if (run.Tag != null)
                {
                    run.FontSize = (double)run.Tag;
                }
            }
            else
            {
                run.Tag = run.FontSize;
                run.FontSize = 0.004;
            }
        }
    }
}

How does this work? When you want to hide a text run, it sets the font size to a really small size — so small you cannot see it. It stores the original font size in the tag property for use later when you want to show it again. It’s that simple.

Below is how you would use the attached property in xaml. In this example, only the text “Speed in MPH” would show up in the UI.

1
2
3
4
<TextBlock TextWrapping="Wrap">
    <Run Text="Speed in KPH" local:RunVisibility.Visible="False"/>
    <Run Text="Speed in MPH" local:RunVisibility.Visible="True"/>
</TextBlock>