0

This is weird. I've created a custom control called Switch. I've also defined a style for TextBlock.

<!-- Switch -->
<Style TargetType="{x:Type controls:Switch}">
    <Setter Property="Margin"
            Value="3,3,3,3" />
    <Setter Property="MinWidth"
            Value="40" />
    <Setter Property="MinHeight"
            Value="24" />
    <Setter Property="On"
            Value="ON" />
    <Setter Property="Off"
            Value="OFF" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type controls:Switch}">
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="Auto" />
                        <ColumnDefinition Width="*" />
                        <ColumnDefinition Width="Auto" />
                    </Grid.ColumnDefinitions>
                    <ContentPresenter Grid.Column="0"
                                      Content="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=Off}" />
                    <Border Grid.Column="1"
                            Background="{TemplateBinding Property=Background}"
                            BorderBrush="{TemplateBinding Property=BorderBrush}"
                            BorderThickness="{TemplateBinding Property=BorderThickness}"
                            CornerRadius="12,12,12,12"
                            HorizontalAlignment="Stretch"
                            VerticalAlignment="Center">
                        <Track x:Name="PART_Track"
                               Minimum="0"
                               Maximum="1" 
                               Orientation="Horizontal"
                               Value="0">
                            <Track.Thumb>
                                <Thumb x:Name="PART_Thumb"
                                       Style="{DynamicResource ResourceKey=SwitchThumb}" />
                            </Track.Thumb>
                        </Track>
                    </Border>
                    <ContentPresenter Grid.Column="2"
                                      Content="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=On}" />
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

<!-- Text Block -->
<Style TargetType="{x:Type TextBlock}">
    <Setter Property="Margin"
            Value="3,3,3,3" />
    <Setter Property="HorizontalAlignment"
            Value="Left" />
    <Setter Property="VerticalAlignment"
            Value="Center" />
    <Setter Property="TextAlignment"
            Value="Left" />
    <Setter Property="TextWrapping"
            Value="Wrap" />
</Style>

When I add an instance of Switch (along with TextBlock style) to a simple window, the ContentPresenter used within the Switch is inheriting TextBlock style.

enter image description here

But when the Switch is used within Visual Studio ToolWindow Extensibility, the ContentPresenter used within the Switch does not inherit the TextBlock style.

Notice the Vertical Alignment and Margin, they are not Center and 3,3,3,3 as set in the Style.

Any idea why?

I tried using snoop to find out the values of the TextBlock within ContentPresenter and they are not according to the style I have defined.

NOTE: I cannot set TextElement Attached Properties on all the ContentPresenters as I have a lot of custom controls and therefore would prefer setting a style for TextBlock instead.

sudarsanyes
  • 3,156
  • 8
  • 42
  • 52

1 Answers1

1

The answer to "why" is probably: the implicit TextBox Style is not being used in the Tool Window.

I wouldn't really care for that though. If I were to style this switch I'd say, OK, I want a little separation between the Track and the labels and I want them all vertically centered. And that's exactly what would go in the Switch style. I wouldn't rely on the textbox to accomplish that. So it'd be like this:

        <ControlTemplate TargetType="{x:Type controls:Switch}">
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="Auto" />
                    <ColumnDefinition Width="*" />
                    <ColumnDefinition Width="Auto" />
                </Grid.ColumnDefinitions>
                <ContentPresenter Grid.Column="0"
                                  Content="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=Off}" VerticalAlignment="Center"/>
                <Border Grid.Column="1"
                        Background="{TemplateBinding Property=Background}"
                        BorderBrush="{TemplateBinding Property=BorderBrush}"
                        BorderThickness="{TemplateBinding Property=BorderThickness}"
                        CornerRadius="12,12,12,12"
                        HorizontalAlignment="Stretch"
                        VerticalAlignment="Center" Margin="3,0">
                    <Track x:Name="PART_Track"
                           Minimum="0"
                           Maximum="1" 
                           Orientation="Horizontal"
                           Value="0">
                        <Track.Thumb>
                            <Thumb x:Name="PART_Thumb"
                                   Style="{DynamicResource ResourceKey=SwitchThumb}" />
                        </Track.Thumb>
                    </Track>
                </Border>
                <ContentPresenter Grid.Column="2"
                                  Content="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=On}" VerticalAlignment="Center"/>
            </Grid>
        </ControlTemplate>
Markus Hütter
  • 7,796
  • 1
  • 36
  • 63
  • 1. Thanks for your answer. What do you mean by " the implicit TextBox Style is not being used in the Tool Window"? 2. Like I mentioned in my post, I am using that textblock style in other controls as well. I do not want to set the Alignment and Margin everywhere. – sudarsanyes Aug 25 '16 at 11:31
  • to answer #1: what exactly do you mean with "Visual Studio ToolWindow Extensibility", I seem to not really get where this would be... to #2 I did read in your question that you don't want to do that. But let's be honest, how many styles do you really have that this would be cumbersome. Furthermore, defining it in your styles is the way to go. Just take a look at [CheckBox's default style](https://msdn.microsoft.com/en-us/library/ms752319(v=vs.110).aspx), see the `Margin` and `VerticalAlignment` in the `ContentPresenter`? – Markus Hütter Aug 25 '16 at 11:52
  • Also, I'm not sure if you set up your DependencyProperties `On` and `Off` to be of type `object` or `string`. If it was `object` that would allow an icon for example and then you would have to specify the margin in the Icon, otherwise the icons would stick to the top and wouldn't have a default margin to the track. So really the margin and vertical alignment belongs rather to the switch than to the switch's contents – Markus Hütter Aug 25 '16 at 11:58
  • I am creating a Tool Window, like Solution Explorer in Visual Studio, using VS Extensibility. – sudarsanyes Aug 25 '16 at 12:35
  • In fact I have created a library of styles for all the out of box WPF controls. I did a quick search and there are around 125 Matches in 24 files. The Tool WIndow is like a browser showing all the styles from Visual Studio so that developers can do a quick glimpse of how the style will look like. So setting margin, alignment, and properties of TextBlocks in 125 places would be difficult to maintain. – sudarsanyes Aug 25 '16 at 12:38
  • So you're coding the tool window yourself and thus also the loading and switching of these styles? Then show the code for loading the styles! – Markus Hütter Aug 25 '16 at 13:31
  • Reading further about ImplicitStyles, I found a blog post on this @ https://blogs.msdn.microsoft.com/wpfsdk/2009/08/27/implicit-styles-templates-controls-and-frameworkelements/ The author has explained this behavior out there. If I add TextBlock Style to Application.Current.Window (even in Visual Studio), the style of TextBlock is applied across all the ContentPresenters. But this Implict Style lookup fails to find the TextBlock style if added only to the container control, instead of Application.Current.Window. – sudarsanyes Aug 25 '16 at 13:37
  • 1
    that was a very interesting read! It kinda does support my argument though. For example: what if a user of your theme uses external libraries like Telerik that you didn't specifically style? Then he would have to deal with the added Margin on all the 'TextBlocks` there... At this point it doesn't matter though, you found the reason yourself and further discussion about how to do it right is primarily opinion-based. – Markus Hütter Aug 26 '16 at 10:59