.NET 6 / WPF : personnaliser le chrome d'une fenêtre

Si vous l'ajoutez à votre code XAML de cette façon :

<Window x:Class="WindowChromeCustomization.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WindowChromeCustomization"
        mc:Ignorable="d"
        Title="MainWindow" Height="300" Width="400">
    <WindowChrome.WindowChrome>
        <WindowChrome />
    </WindowChrome.WindowChrome>
    <Grid Background="DarkGray"/>
</Window>

Vous obtenez une fenêtre où le titre et les boutons systèmes (minimiser, maximiser...) ont disparu :

Plus de titre, plus de boutons

Mais bizarrement, les fonctionnalités sont toujours là : si on double clique sur le haut, la fenêtre est maximisée et si on clique en haut à droite la fenêtre se ferme. C'est un peu bizarre...

En fait, il faut modifier le gabarit de la fenêtre de cette façon :

<Window x:Class="WindowChromeCustomization.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d"
        Title="MainWindow" Height="300" Width="400">
    <WindowChrome.WindowChrome>
        <WindowChrome/>
    </WindowChrome.WindowChrome>
    <Window.Style>
        <Style TargetType="Window">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="Window">
                        <Grid>
                            <ContentPresenter Content="{TemplateBinding Content}" Margin="{x:Static SystemParameters.WindowNonClientFrameThickness}"/>  
                        </Grid>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </Window.Style>
    <Grid Background="DarkGray"/>
</Window>

On doit ajouter un élément ContentPresenter avec des marges correspondant à celles fournies par la propriété système WindowNonClientFrameThickness (4,27,4,4 sur mon système). Cet élément ContentPresenter va afficher la zone non cliente. Notez que l'élément ContentPresenter doit être placé dans un conteneur comme Grid pour que la propriété Margin soit prise en compte.

Si maintenant vous voulez changer la couleur de la bordure, vous vous dites peut-être qu'il suffit de changer le Background de l'élément Grid. Mais en fait si vous définissez cette propriété, les boutons système vont disparaitre, car la grille, transparente jusqu'ici, est maintenant opaque et masque les boutons (qui continuent à fonctionner malgré tout).

Donc on peut ajouter des éléments à la zone non cliente, par exemple le titre de la fenêtre :

<Grid>
    <TextBlock Text="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Title}" Margin="11,6,0,0" />
    <ContentPresenter Content="{TemplateBinding Content}" Margin="{x:Static SystemParameters.WindowNonClientFrameThickness}"/>  
</Grid>

Mais si on veut changer la couleur de la bordure, et bien on doit passer la propriété UseAeroCaptionButtons à False pour désactiver les boutons (notez qu'ils sont inactifs mais toujours dessinés) et les réimplémenter.

Et ce n'est pas le seul problème auquel on est confronté avec WindowChrome. Dans un prochain article, on verra qu'on a un soucis si on maximise la fenêtre...

Etiquettes:

Add new comment