La classe Control espone una proprietà Template che permette di ridefinire il Visual Tree associato, in parole povere è possibile stravolgerne la UI mantenendo inalterato il comportamento.
Ci sono varie alternative per agire sulla proprietà, un metodo possibile è quello inline:
<Button>
<Button.Template>
<ControlTemplate>
<CheckBox>Hello</CheckBox>
</ControlTemplate>
</Button.Template>
</Button>
Ottenendo in questo caso un button che si presenta come una checkbox (???)
La modalità comune di utilizzo di un template è comunque attraverso gli stili, non a caso nel SDK si trova la descrizione dei vari stili utilizzati dai controlli comuni(button, checkbox, listbox...)
Un esempio di stile, applicato al tipo Button è la seguente
<Style TargetType="{x:Type Button}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Viewbox Stretch="Fill" Width="{TemplateBinding Property=Width}" Height="{TemplateBinding Property=Height}">
<Grid>
<Rectangle RadiusX="20" RadiusY="20" Stroke="Blue" Width="100" Height="50" StrokeThickness="2" x:Name="r1">
<Rectangle.Fill>
<LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
<LinearGradientBrush.GradientStops>
<GradientStop Color="#F53" Offset="0" />
<GradientStop Color="#FAA" Offset="1" />
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
<ContentPresenter Margin="2" HorizontalAlignment="Center" VerticalAlignment="Center" Content="{TemplateBinding Property=Button.Content}"/>
</Grid>
</Viewbox>
<ControlTemplate.Triggers>
<Trigger Property="Button.IsMouseOver" Value="true" >
<Setter TargetName="r1" Property="Opacity" Value="0.2" />
<Setter TargetName="r1" Property="StrokeThickness" Value="4" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Questa "vagonata" di XAML definisce uno style per il tipo Button (x:Type Button) che agisce sulla proprietà Template e il valore che applicherà sarà un ControlTemplate all'interno del quale troviamo i vari Visuals che descrivono quale sarà la user interface del Button al quale verrà applicato lo stile.
In questo caso la UI è composta da un Rettangolo sfumato e da un oggetto ContentPresenter il quale ha come unico scopo quello di definire un area che verrà occupata con ciò che verrà restituito dalla rispettiva proprietà Content.
Quest'ultima, come altre proprietà presenti nel ContentTemplate, ha una particolarità: quella di ereditare il proprio valore dal controllo al quale il template è associato permettendo quindi di 'parametrizzare' alcuni aspetti del template stesso, il tutto grazie all'uso di una particolare forma di Binding definita TemplateBinding che lega la proprietà del template con quella del parent.
Nello specifico caso della definizione del ContenPresenter:
<ContentPresenter Margin="2" HorizontalAlignment="Center" VerticalAlignment="Center" Content="{TemplateBinding Property=Button.Content}"/>
Ne deriva che all'interno del ContentPresenter verrà visualizzato il valore della proprietà Content del button associato quindi, come solitamente accade, il testo del pulsante.
In un ContentTemplate è anche possibile definire dei Triggers che modificano dinamicamente l'aspetto del controllo, nel frammento sopra riportato quando il mouse è sopra il pulsante viene cambiata l'opacità e la dimensione del bordo.
Un dettaglio interessante è che per agire esplicitamente su un elemento contenuto nel ContentTemplate il setter usa in questo caso la proprietà TargetName.
Utilizzando lo stile appena descritto e questo snippet
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
<Button Width="200" Height="100">Btn1</Button>
<Button Width="100" Height="75">Btn2</Button>
<Button Width="80" Height="100">Btn3</Button>
</StackPanel>
Il risultato finale è: