William
William

Reputation: 1895

How does a WPF button allow the content to be set without losing its core appearance?

This is some what of a silly question, but also one which is confusing me of how it could possibly work. Suppose I have my own UserControl defined which extends ContentControl and provides this:

<Grid x:Name="William">

    <Grid.RowDefinitions>
        <RowDefinition Height="*"/>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="Auto"/>
    </Grid.RowDefinitions>
    <TextBox Text="{Binding RelativeSource={RelativeSource Self}, Path=FontSize, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"></TextBox>
    <Button HorizontalAlignment="Center"  Content="{Binding Time}" Grid.Row="1" CommandTarget="{Binding RelativeSource={RelativeSource AncestorType=Grid}}" Command="{x:Static local:Commands.Foo}">
    </Button>
</Grid>

Ignoring the bindings, the important thing is this is the content of my UserControl.

I create an instance of my user control in my main Window like so:

<local:UserControl1 x:Name="myC" Grid.Row="1" DataContext="{Binding ChildName}">
    </local:UserControl1>

And all works fine. Now I can override my content defined in the user control like this:

<local:UserControl1 x:Name="myC" Grid.Row="1" DataContext="{Binding ChildName}">
Hello!
    </local:UserControl1>

And the whole content get's replaced with the text 'Hello!'

But a button allows me to set the content, but still keeps a button there:

<Button x:Name="testBt">
        Hello!
    </Button>

enter image description here

Could someone explain why this is?

Updated with full control:

<UserControl
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
         xmlns:local="clr-namespace:RoutedCommandDemo"
         xmlns:dates="clr-namespace:System;assembly=mscorlib" xmlns:Linq="clr-namespace:System.Xml.Linq;assembly=System.Xml.Linq" x:Class="RoutedCommandDemo.UserControl1" 
         mc:Ignorable="d" 
         d:DesignHeight="300" d:DesignWidth="300"
         >

<UserControl.Resources>

    <Style TargetType="Button">
        <Style.Setters>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="Button">
                        <Grid>
                            <Border Background="{TemplateBinding BorderBrush}" Margin="5 5 0 0" />
                            <Border BorderBrush="Black" BorderThickness="1"
            Background="{TemplateBinding Background}" Margin="0 0 5 5">
                                <ContentPresenter HorizontalAlignment="{TemplateBinding Property=HorizontalAlignment}"
                                      VerticalAlignment="Center"/>

                            </Border>
                        </Grid>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
            <Setter Property="Background" Value="Yellow"></Setter>
            <Setter Property="BorderBrush" Value="Red"></Setter>
        </Style.Setters>
        <Style.Triggers>
            <Trigger Property="IsMouseOver" Value="True">
                <Setter Property="Background"  Value="Pink"></Setter>
                <Setter Property="BorderBrush" Value="Green"></Setter>
            </Trigger>
        </Style.Triggers>
    </Style>
    <Style TargetType="local:UserControl1">
        <Style.Setters>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="local:UserControl1">
                        <Grid>
                            <Grid.RowDefinitions>
                                <RowDefinition Height="*"></RowDefinition>
                                <RowDefinition Height="*"></RowDefinition>
                                <RowDefinition Height="*"></RowDefinition>
                            </Grid.RowDefinitions>

                            <ContentPresenter Content="{TemplateBinding Content}" HorizontalAlignment="{TemplateBinding Property=HorizontalAlignment}"
                                      VerticalAlignment="Center"/>

                            <TextBox Grid.Row="1" Text="{Binding RelativeSource={RelativeSource Self}, Path=FontSize, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"></TextBox>
                            <Button Grid.Row="2" HorizontalAlignment="Center"  Content="{Binding Time}" CommandTarget="{Binding RelativeSource={RelativeSource AncestorType=Grid}}" Command="{x:Static local:Commands.Foo}">
                            </Button>
                        </Grid>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style.Setters>
    </Style>
</UserControl.Resources>


<UserControl.CommandBindings>
    <CommandBinding Command="{x:Static local:Commands.Foo}" Executed="CommandBinding_Executed"/>

</UserControl.CommandBindings>
<UserControl.InputBindings>
    <KeyBinding Command="{x:Static local:Commands.Foo}" Modifiers="Control"  Key="Space"></KeyBinding>
</UserControl.InputBindings>

Upvotes: 1

Views: 411

Answers (1)

Lucas Trzesniewski
Lucas Trzesniewski

Reputation: 51430

The button has a control template.

Take a look at this MSDN page: Button Styles and Templates. It lists the default button style.

Notice the following:

<Setter Property="Template">
    <Setter.Value>
        <ControlTemplate TargetType="Button">
            <Grid>
                ...
                <Border x:Name="Background" ...>
                    ...
                </Border>
                <ControlPresenter Content="{TemplateBinding Content}" ... />
                <Rectangle x:Name="DisabledVisualElement" ... />
                <Rectangle x:Name="FocusVisualElement" ... />
                ...

What you're seeing behind the "Hello" text is the Background Border element. The content itself is rendered by the ContentPresenter.

Visual themes define these default styles (so you get a different look on WinXP/Win7/Win10 etc). They can also be overridden by application styles.

For obvious reasons, UserControl has no predefined appearance.

See here or here for some details.

Upvotes: 1

Related Questions