PasswordBox does not apply style
Asked Answered
M

3

10

I have the following style definitions:

<!-- Border -->
<Style x:Key="MyControlBorder" TargetType="{x:Type Border}">
    <Setter Property="BorderBrush" Value="DarkKhaki" />
    <Setter Property="Background" Value="White" />
    <Setter Property="BorderThickness" Value="1" />
    <Setter Property="CornerRadius" Value="10" />
</Style>

<!-- TextBox -->
<Style x:Key="MyTextBox" TargetType="{x:Type TextBox}">
    <Setter Property="Height" Value="30" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type TextBoxBase}">
                <Border Name="TextBoxBorder" Style="{StaticResource MyControlBorder}">
                    <ScrollViewer x:Name="PART_ContentHost"/>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

<!-- PasswordBox -->
<Style x:Key="MyPasswordBox" TargetType="{x:Type PasswordBox}">
    <Setter Property="Height" Value="30" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type Control}">
                <Border Name="Border" Style="{StaticResource MyControlBorder}">
                    <ScrollViewer x:Name="PART_ContentHost" />
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

And the following XAML code:

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="*" />
        <RowDefinition Height="*" />
    </Grid.RowDefinitions>
    <TextBox Grid.Row="0" Style="{StaticResource MyTextBox}" />
    <PasswordBox Grid.Row="1" Style="{StaticResource MyPasswordBox}" />
</Grid>

Now I got this result: A TextBox and a PasswordBox stacked vertically, where the TextBox has a khaki colored, rounded border, but the PasswordBox has no border at all.

The TextBox applies the style correctly, but why does the PasswordBox not apply the style?

Morehead answered 4/6, 2013 at 6:41 Comment(1)
Have you tried using something like Snoop for finding out where the border is getting it's values from at runtime? It's possible something is setting the border styles at a higher Dependency Property PrecedenceCapparidaceous
H
2

Somehow Border within ControlTemplate of PasswordBox does not take MyControlBorder style.

When you modify MyPasswordBox style like this... then it will work.

<Style x:Key="MyPasswordBox" TargetType="{x:Type PasswordBox}">
<Setter Property="Height" Value="30" />
<Setter Property="Template">
    <Setter.Value>
        <ControlTemplate TargetType="{x:Type Control}">
            <Border Name="Border" BorderBrush="DarkKhaki" Background="White" BorderThickness="1" CornerRadius="10">
                <ScrollViewer x:Name="PART_ContentHost" />
            </Border>
        </ControlTemplate>
    </Setter.Value>
</Setter>

I know it's not the best solution... but I can't figure out why MyControlBorder is not applied. It doesn't even work when you get rid of MyTextBox style. Then you are left only with MyControlBorder and MyPasswordBox ...it does not work either.

Helgeson answered 4/6, 2013 at 10:26 Comment(0)
B
3

If you wrap the Border in another Border everything just works as expected (I don't know why).

As a bonus, you can now have PasswordBoxes and TextBoxes "inherit" from the same Style, keeping things nice and DRY.

<!-- Border Style Definition -->
<Style x:Key="MyControlBorder" TargetType="Border">
    <Setter Property="BorderBrush" Value="DarkKhaki" />
    <Setter Property="Background" Value="White" />
    <Setter Property="BorderThickness" Value="1" />
    <Setter Property="CornerRadius" Value="10" />
</Style>

<!-- TextBox and PasswordBox Style -->
<Style x:Key="MyControlInputBox" TargetType="Control">
    <Setter Property="Height" Value="30" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type Control}">
                <Border>
                    <Border Name="Border" Style="{StaticResource MyControlBorder}">
                        <ScrollViewer x:Name="PART_ContentHost" />
                    </Border>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

<!-- TextBox -->
<Style x:Key="MyTextBox" TargetType="{x:Type TextBox}" BasedOn="{StaticResource MyControlInputBox}" />

<!-- PasswordBox -->
<Style x:Key="MyPasswordBox" TargetType="{x:Type PasswordBox}" BasedOn="{StaticResource MyControlInputBox}" />
Byrom answered 13/2, 2014 at 20:55 Comment(2)
css is awesome, xaml not so awesome :POstia
I also added '<Setter Property="Padding" Value="6"></Setter>' to MyControlInputBox, otherwise the cursor was too high.Ostia
H
2

Somehow Border within ControlTemplate of PasswordBox does not take MyControlBorder style.

When you modify MyPasswordBox style like this... then it will work.

<Style x:Key="MyPasswordBox" TargetType="{x:Type PasswordBox}">
<Setter Property="Height" Value="30" />
<Setter Property="Template">
    <Setter.Value>
        <ControlTemplate TargetType="{x:Type Control}">
            <Border Name="Border" BorderBrush="DarkKhaki" Background="White" BorderThickness="1" CornerRadius="10">
                <ScrollViewer x:Name="PART_ContentHost" />
            </Border>
        </ControlTemplate>
    </Setter.Value>
</Setter>

I know it's not the best solution... but I can't figure out why MyControlBorder is not applied. It doesn't even work when you get rid of MyTextBox style. Then you are left only with MyControlBorder and MyPasswordBox ...it does not work either.

Helgeson answered 4/6, 2013 at 10:26 Comment(0)
S
0

The PasswordBox is strange in this regard, as it is explicitly implemented to show this behavior.

The default control template contains a Border, as you can see here:

<ControlTemplate TargetType="{x:Type PasswordBox}">
   <Border x:Name="border" Background="{TemplateBinding Background}" BorderThickness="{TemplateBinding BorderThickness}" BorderBrush="{TemplateBinding BorderBrush}" SnapsToDevicePixels="True">
      <ScrollViewer x:Name="PART_ContentHost" Focusable="false" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden"/>
   </Border>
   <!-- ...other markup, triggers. -->
</ControlTemplate>

The code for PasswordBox (taken from reference source) does the following:

Consequently, whenever a control template is applied, the Style of the outermost Border is reset. This is still the same in .NET Core and >.NET , as you can see from the code on GitHub. This is the reason why @David Murdoch's answer with a redundant nested Border works, when the style is applied to the inner Border.

Now, what can do? You can either insert a dummy Border as a workaround or you have to set the CornerRadius directly to the Border inside your custom control template.

<ControlTemplate TargetType="{x:Type Control}">
   <Border Name="Border" CornerRadius="10" Style="{StaticResource MyControlBorder}">
      <ScrollViewer x:Name="PART_ContentHost" />
   </Border>
</ControlTemplate>
Soybean answered 22/3, 2022 at 17:29 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.