Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why doesn't my TextBlock/TextBox apply values from a Base Style?

It's not uncommon for me to write something like below for styling a data entry form, but my problem is that TextBox and TextBlock don't seem to implement the Setters that are in the BaseElementStyle. Usually I need to define them separately.

Why is this? And is there a way around it?

I am guessing it has to do with the fact they are usually used in other control templates (for example TextBlock is used in most controls and TextBox is used in DatePickers and ComboBoxes)

<Style x:Key="BaseElementStyle" TargetType="{x:Type FrameworkElement}">
    <Setter Property="Margin" Value="5" />
    <Setter Property="VerticalAlignment" Value="Center" />
</Style>
<Style TargetType="{x:Type TextBlock}" BasedOn="{StaticResource BaseElementStyle}" />
<Style TargetType="{x:Type TextBox}" BasedOn="{StaticResource BaseElementStyle}" />
<Style TargetType="{x:Type Label}" BasedOn="{StaticResource BaseElementStyle}" />
<Style TargetType="{x:Type ComboBox}" BasedOn="{StaticResource BaseElementStyle}" />
<Style TargetType="{x:Type DatePicker}" BasedOn="{StaticResource BaseElementStyle}" />
<Style TargetType="{x:Type CheckBox}" BasedOn="{StaticResource BaseElementStyle}" />
like image 742
Rachel Avatar asked Sep 29 '11 12:09

Rachel


2 Answers

I would like to suggest the two possible workarounds. It seems that each of Key and Type can be used but both of them cannot be used together as your question case, x:Key="BaseElementStyle" TargetType="{x:Type FrameworkElement}".

  1. using x:Key

    <Style x:Key="BaseElementStyle">
        <Setter Property="FrameworkElement.Margin" Value="5" />
        <Setter Property="FrameworkElement.VerticalAlignment" Value="Center" />
    </Style>
    <Style TargetType="{x:Type TextBlock}" BasedOn="{StaticResource BaseElementStyle}" />
    <Style TargetType="{x:Type TextBox}" BasedOn="{StaticResource BaseElementStyle}" />
    <Style TargetType="{x:Type Label}" BasedOn="{StaticResource BaseElementStyle}" />
    <Style TargetType="{x:Type ComboBox}" BasedOn="{StaticResource BaseElementStyle}" />
    <Style TargetType="{x:Type DatePicker}" BasedOn="{StaticResource BaseElementStyle}" />
    <Style TargetType="{x:Type CheckBox}" BasedOn="{StaticResource BaseElementStyle}" />
    
  2. using x:Type

    <Style TargetType="{x:Type FrameworkElement}">
        <Setter Property="Margin" Value="5" />
        <Setter Property="VerticalAlignment" Value="Center" />
    </Style>
    <Style TargetType="{x:Type TextBlock}" BasedOn="{StaticResource {x:Type FrameworkElement}}" />
    <Style TargetType="{x:Type TextBox}" BasedOn="{StaticResource {x:Type FrameworkElement}}" />
    <Style TargetType="{x:Type Label}" BasedOn="{StaticResource {x:Type FrameworkElement}}" />
    <Style TargetType="{x:Type ComboBox}" BasedOn="{StaticResource {x:Type FrameworkElement}}" />
    <Style TargetType="{x:Type DatePicker}" BasedOn="{StaticResource {x:Type FrameworkElement}}" />
    <Style TargetType="{x:Type CheckBox}" BasedOn="{StaticResource {x:Type FrameworkElement}}" />
    
like image 74
Jin-Wook Chung Avatar answered Sep 28 '22 03:09

Jin-Wook Chung


Also keep in mind that WPF considers a ControlTemplate to be an inflation boundary and does NOT apply default styles inside of templates. The exception to the rule: anything that inherits from Control WILL BE inflated with the default style. Since TextBlock inherits from FrameworkElement and not from Control, if you use of it inside of a ControlTemplate you will also have to apply it's style manually. This is true for both TextBlocks that are added by hand, or by TextBlocks added by WPF for string Content. A quick example:

<Window x:Class="ImplicitStyles.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <StackPanel>
        <StackPanel.Resources>
            <Style x:Key="BaseElementStyle">
                <Setter Property="FrameworkElement.Tag" Value="Hello World" />
            </Style>
            <Style TargetType="{x:Type Button}" BasedOn="{StaticResource BaseElementStyle}" />
            <Style TargetType="{x:Type TextBlock}" BasedOn="{StaticResource BaseElementStyle}" />

            <!-- Default style for TextBlock will not be applied, Tag will be null -->
            <ControlTemplate x:Key="MyContentControlTemplateOne" TargetType="{x:Type ContentControl}">
                <Border BorderBrush="Red" BorderThickness="2">
                    <TextBlock Text="{Binding RelativeSource={RelativeSource Self}, Path=Tag}" />
                </Border>
            </ControlTemplate>

            <!-- Default style for Button will be applied, Tag will be Hello World -->    
            <ControlTemplate x:Key="MyContentControlTemplateTwo" TargetType="{x:Type ContentControl}">
                <Border BorderBrush="Red" BorderThickness="2">
                    <Button Content="{Binding RelativeSource={RelativeSource Self}, Path=Tag}" />
                </Border>
            </ControlTemplate>

        </StackPanel.Resources>

        <ContentControl Template="{StaticResource MyContentControlTemplateOne}" />
        <ContentControl Template="{StaticResource MyContentControlTemplateTwo}" />
    </StackPanel>

</Window>

For more information, see this blog post:

http://blogs.msdn.com/b/wpfsdk/archive/2009/08/27/implicit-styles-templates-controls-and-frameworkelements.aspx

like image 30
FunnyItWorkedLastTime Avatar answered Sep 28 '22 04:09

FunnyItWorkedLastTime