简体   繁体   中英

Override property of custom control style in XAML

I borrowed some code from some other guy here on Stack Overflow. I have two PasswordBoxes. I want the first one to show "Password" and the second one to show "Re-enter Password". I don't want to rewrite the complete style all over again if the only difference is the text in the TextBlock. How can I override and change the value of the TextBlock, if the TargetType has to be PasswordBox? I'm trying to create a second style that is based on the first one, and then change it from there, but I'm not sure about the syntax.

This one works fine:

    <Style x:Name="customPWBStyle" x:Key="customPasswordBox" 
    TargetType="{x:Type PasswordBox}">
        <Setter Property="helper:PasswordBoxMonitor.IsMonitoring"
          Value="True"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type PasswordBox}">
                    <Border Name="Bd"
                Background="{TemplateBinding Background}"
                BorderThickness="{TemplateBinding BorderThickness}"
                BorderBrush="{TemplateBinding BorderBrush}"
                SnapsToDevicePixels="true">
                        <Grid>
                            <ScrollViewer x:Name="PART_ContentHost"
                          SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
                            <TextBlock Text="Password" 
                       Margin="4, 2, 0, 0"
                       Foreground="Gray" 
                       Visibility="Collapsed"
                       Name="txtPrompt" />
                        </Grid>
                    </Border>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsEnabled"
                                     Value="false">
                            <Setter TargetName="Bd"
                                        Property="Background"
                                        Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/>
                            <Setter Property="Foreground"
                                        Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
                        </Trigger>
                        <Trigger Property="helper:PasswordBoxMonitor.PasswordLength" Value="0">
                            <Setter Property="Visibility" TargetName="txtPrompt" Value="Visible"/>
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

But I want to create another style identical, but the only difference has to be the TextBlock that has to say "Re-enter password"

This is what I got so far:

        <Style x:Key="reEnterPasswordBox" BasedOn="{StaticResource customPasswordBox}" TargetType="{x:Type PasswordBox}">
        <Style.Resources>
            <Style TargetType="TextBlock">
                <Setter Property="Text" Value="Re-enter Password"></Setter>
            </Style>
        </Style.Resources>            
    </Style>

However it does not work. I can see that theres a name for the TextBlock, which is txtPrompt, but I'm not sure if its possible to use that as a reference for chaning the value of the TextBlock.

I would recommend to create a special dependency property in customPasswordBox, eg InputHint. (If you can't change customPasswordBox code, make a custom attached dependency property - like helper:PasswordBoxMonitor.IsMonitoring. Attached DPs are great for parametrizing templates)

When you have a property, set default value via Setter, and then bind TextBlock to it via TemplateBinding.

<Style x:Name="customPWBStyle" x:Key="customPasswordBox" 
       TargetType="{x:Type PasswordBox}">
    <Setter Property="helper:PasswordBoxMonitor.IsMonitoring" Value="True"/>
    <Setter Property="InputHint" Value="Password"/>

    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type PasswordBox}">
                <Border Name="Bd"
                        Background="{TemplateBinding Background}"
                        BorderThickness="{TemplateBinding BorderThickness}"
                        BorderBrush="{TemplateBinding BorderBrush}"
                        SnapsToDevicePixels="true">
                    <Grid>
                        <ScrollViewer x:Name="PART_ContentHost"
                                      SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
                        <TextBlock Text="{TemplateBinding InputHint}" 
                                   Margin="4, 2, 0, 0"
                                   Foreground="Gray" 
                                   Visibility="Collapsed"
                                   Name="txtPrompt" />
                    </Grid>
                </Border>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsEnabled"
                                 Value="false">
                        <Setter TargetName="Bd"
                                    Property="Background"
                                    Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/>
                        <Setter Property="Foreground"
                                    Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
                    </Trigger>
                    <Trigger Property="helper:PasswordBoxMonitor.PasswordLength" Value="0">
                        <Setter Property="Visibility" TargetName="txtPrompt" Value="Visible"/>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

to make another style, change only Setter for InputHint:

<Style x:Key="reEnterPasswordBox" BasedOn="{StaticResource customPasswordBox}" TargetType="{x:Type PasswordBox}">
    <Setter Property="InputHint" Value="Re-enter Password"/>          
</Style>

Parts of template are not easily reachable for modification, even with implicit styles

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM