简体   繁体   中英

WPF CustomControl style not inherited by Child Control

I'm trying to learn how to make a custom control. I've been searching all afternoon, but can't get my properties to be used by the child controls.

For example my TextBox subclass is TextBoxCalculator. In the control template I have a textbox and a popup.

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:local="clr-namespace:Controls">

    <Style TargetType="local:TextBoxCalculator" BasedOn="{StaticResource {x:Type TextBox}}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="local:TextBoxCalculator">

                    <Grid Name="ucGrid">
                        <TextBox Name="AmountTb" Text="{Binding Text }">
                            <!--<TextBox.Style>
                                <Style TargetType="{x:Type TextBox}" BasedOn="{StaticResource {x:Type TextBox}}">
                                ... How can I make this textbox style follow the one specified in the window XAML?
                                </Style>
                            </TextBox.Style>-->
                        </TextBox>
                        <Popup Name="calPopup"  Placement="Top" StaysOpen="False">
                          ... some content
                        </Popup>
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</ResourceDictionary>

In my window I use the control like this:

    <Style TargetType="{x:Type controls1:TextBoxCalculator}" x:Key="RightCellEditCalc">
        <Setter Property="HorizontalAlignment" Value="Stretch"/>
        <Setter Property="TextAlignment" Value="Right"/>
        <Setter Property="Background" Value="Red"/>
        <Setter Property="BorderThickness" Value="0"/>
    </Style>

<controls1:TextBoxCalculator Text="{Binding Amount, UpdateSourceTrigger=LostFocus}" 
                        DecimalPlaces="2"
                        AutoPlaceDecimalPoint="True"
                        Style="{StaticResource RightCellEditCalc}"
                        Background="Green">
</controls1:TextBoxCalculator>

I would expect the background to be green, but it is white instead. An the other hand the TextAlignment = Right seems to be working. What am I missing?

It makes no sense to define a TextBox element in the ControlTemplate of another custom TextBox control.

If you want to create a custom template for your control and base it on the default template of the TextBox control, you could right-click on a TextBox element in design mode in Visual Studio or in Blend and choose Edit Template->Edit a Copy to copy the default template into your XAML markup and then edit it as per your requirements.

This is how it looks like on Windows 8 and later:

<ControlTemplate TargetType="{x:Type TextBox}">
    <Border x:Name="border" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True">
        <ScrollViewer x:Name="PART_ContentHost" Focusable="false" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden"/>
    </Border>
    <ControlTemplate.Triggers>
        <Trigger Property="IsEnabled" Value="false">
            <Setter Property="Opacity" TargetName="border" Value="0.56"/>
        </Trigger>
        <Trigger Property="IsMouseOver" Value="true">
            <Setter Property="BorderBrush" TargetName="border" Value="#FF7EB4EA"/>
        </Trigger>
        <Trigger Property="IsKeyboardFocused" Value="true">
            <Setter Property="BorderBrush" TargetName="border" Value="#FF569DE5"/>
        </Trigger>
    </ControlTemplate.Triggers>
</ControlTemplate>

It uses TemplateBindings to bind properties of the Border element in the template to the corresponding property of the TextBox control itself.

You are not binding the background.binding it at the place you want inside your ControlTemplate.For example

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                xmlns:local="clr-namespace:Controls">

<Style TargetType="local:TextBoxCalculator" BasedOn="{StaticResource {x:Type TextBox}}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="local:TextBoxCalculator">

                <Grid Name="ucGrid">
                    <TextBox Name="AmountTb" Text="{Binding Text }" Background="{TemplateBinding Background}">
                        <!--<TextBox.Style>
                            <Style TargetType="{x:Type TextBox}" BasedOn="{StaticResource {x:Type TextBox}}">
                            ... How can I make this textbox style follow the one specified in the window XAML?
                            </Style>
                        </TextBox.Style>-->
                    </TextBox>
                    <Popup Name="calPopup"  Placement="Top" StaysOpen="False">
                    </Popup>
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

you can use the background now.

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