Jehof
Jehof

Reputation: 35544

Change style of TextBlock for TargetNullValue

I want to change the Style of a TextBlock if the value of the bound property is null. I have specified a value for TargetNullValue of the TextBlock to be displayed, but i want to display it with an alternativ style. How can i do it.

My current solution is to use two TextBlocks and control the Visibility of both, to toggle between original and alternativ style. But this solution is not viable, cause i need to duplicate each TextBlock, for displaying alternativ version.

Current Solution:

<TextBlock Visibility="{Binding MyText, Converter={StaticResource nullToVisibilityConverter}}"
           FontSize="20"
           Foreground="Black"
           Text="{Binding MyText}" />

<TextBlock Visibility="{Binding MyText, Converter={StaticResource nullToVisibilityConverter}}"
           FontSize="20"
           FontStyle="Italic"
           Foreground="Gray"
           Text="None" />

Needed Solution:

<TextBlock FontSize="20"
           Foreground="Black"
           Text="{Binding MyText, TargetNullValue='None'}" />

<!-- plus any styles, templates or triggers, to change style of TextBlock for TargetNullValue -->

How can i use an alternativ style for a TargetNullValue. Any solutions using Styles, Triggers or Templates are welcome.

Upvotes: 4

Views: 1620

Answers (1)

erodewald
erodewald

Reputation: 1825

Note: this is for WPF, you might have to convert anything that doesn't quite mesh with SL5.0.

The easiest solution (unless this requirement is ubiquitous) is to make a specific style for each instance which binds to the same property as the textblock, checks for Null and sets properties there.

This example will paste nicely into Kaxaml.

  <Style x:Key="tacoStyle" TargetType="TextBlock">
    <Style.Triggers>
      <DataTrigger Binding="{Binding Source={StaticResource taco}}" Value="{x:Null}">
        <Setter Property="Foreground" Value="Red"/>
      </DataTrigger>
    </Style.Triggers>
  </Style>
</StackPanel.Resources>
<TextBlock Style="{StaticResource tacoStyle}" Text="{Binding Source={StaticResource taco}, TargetNullValue='bacon'}"/>

Of course if you need a more generic solution, you could extend TextBlock and add some logic to handle this.

<StackPanel>
        <StackPanel.Resources>
            <x:NullExtension x:Key="taco"/>
            <Style x:Key="AltTacoStyle" TargetType="yourNS:ExtendedTextBlock">
                <Setter Property="Foreground" Value="Pink"/>
            </Style>
        </StackPanel.Resources>
        <yourNS:ExtendedTextBlock Text="{Binding Source={StaticResource taco}, TargetNullValue='bacon'}"
                                                                                AltStyle="{StaticResource AltTacoStyle}"
                                                                                AllowAltStyleOnNull="True"/>
    </StackPanel>

And the control:

    public class ExtendedTextBlock : TextBlock {


    public static readonly DependencyProperty AllowAltStyleOnNullProperty =
        DependencyProperty.Register("AllowAltStyleOnNull", typeof (bool), typeof (ExtendedTextBlock), new PropertyMetadata(default(bool)));

    public bool AllowAltStyleOnNull {
        get { return (bool) GetValue(AllowAltStyleOnNullProperty); }
        set { SetValue(AllowAltStyleOnNullProperty, value); }
    }

    public static readonly DependencyProperty AltStyleProperty =
        DependencyProperty.Register("AltStyle", typeof (Style), typeof (ExtendedTextBlock), new PropertyMetadata(default(Style)));

    public Style AltStyle {
        get { return (Style) GetValue(AltStyleProperty); }
        set { SetValue(AltStyleProperty, value); }
    }

    static ExtendedTextBlock() {
        TextProperty.OverrideMetadata(typeof(ExtendedTextBlock), new FrameworkPropertyMetadata(default(string), PropertyChangedCallback));
    }

    private static void PropertyChangedCallback(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs) {
        var tb = (ExtendedTextBlock)dependencyObject;
        var binding = tb.GetBindingExpression(TextProperty);
        if (binding != null && binding.DataItem == null) {
            if (tb.AllowAltStyleOnNull)
                tb.Style = tb.AltStyle;
        }
    }
}

You'll need to flesh that out a bit to be production-ready, but you get the idea.

Upvotes: 1

Related Questions