Partager via


Que sont les contrôles ?

Windows Presentation Foundation (WPF) est fourni avec la plupart des composants d’interface utilisateur courants utilisés dans presque toutes les applications Windows, telles que Button, , Label, TextBox, Menuet ListBox. Historiquement, ces objets sont appelés contrôles. Le terme « contrôle » est utilisé librement pour désigner toute classe qui représente un objet visible dans une application. Il est important de noter qu’une classe n’a pas besoin d’hériter de la Control classe pour avoir une présence visible. Les classes qui héritent de la Control classe contiennent un ControlTemplate, qui permet au consommateur d’un contrôle de modifier radicalement l’apparence du contrôle sans avoir à créer de sous-classe. Cet article explique comment les contrôles (à la fois ceux qui héritent de la Control classe et ceux qui ne l’ont pas) sont couramment utilisés dans WPF.

Créer une instance d’un contrôle

Vous pouvez ajouter un contrôle à une application à l’aide du langage XAML (Extensible Application Markup Language) ou du code. Par exemple, considérez l’image suivante d’une fenêtre WPF qui demande à un utilisateur son nom et son adresse :

Capture d’écran d’une application WPF avec deux zones de texte étiquetées nom et adresse. Deux boutons sont visibles. Un bouton est nommé « Réinitialiser » et l’autre « Submit ».

Cette fenêtre comporte six contrôles : deux étiquettes, deux zones de texte et deux boutons. XAML est utilisé pour créer ces contrôles, comme illustré dans l’extrait de code suivant :

<Window x:Class="Examples.ExampleApp"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Input Record" Height="Auto" Width="300" SizeToContent="Height">
    <Grid Margin="5">
        <Grid.RowDefinitions>
            <RowDefinition Height="30"/>
            <RowDefinition Height="30"/>
            <RowDefinition Height="30"/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>

        <Label>Enter your name:</Label>
        <TextBox Grid.Row="0" Grid.Column="1" Name="FirstName" Margin="2" />

        <Label Grid.Row="1">Enter your address:</Label>
        <TextBox Grid.Row="1" Grid.Column="1" Name="LastName" Margin="2" />

        <Button Grid.Row="2" Grid.Column="0" Name="Reset" Margin="2">Reset</Button>
        <Button Grid.Row="2" Grid.Column="1" Name="Submit" Margin="2">Submit</Button>
    </Grid>
</Window>

Tous les contrôles peuvent être créés de la même façon en XAML. La même fenêtre peut être créée dans le code :

// Grid container which is the content of the Window
Grid container = new() { Margin = new Thickness(5) };
container.RowDefinitions.Add(new RowDefinition());
container.RowDefinitions.Add(new RowDefinition());
container.RowDefinitions.Add(new RowDefinition());
container.ColumnDefinitions.Add(new ColumnDefinition());
container.ColumnDefinitions.Add(new ColumnDefinition());

// Create the two labels, assign the second label to the second row
Label labelName = new() { Content = "Enter your name:" };
container.Children.Add(labelName);

Label labelAddress = new() { Content = "Enter your address:" };
Grid.SetRow(labelAddress, 1);
container.Children.Add(labelAddress);

// Create the two textboxes, assign both to the second column and
// assign the second textbox to the second row.
TextBox textboxName = new() { Margin = new Thickness(2) };
Grid.SetColumn(textboxName, 1);
container.Children.Add(textboxName);

TextBox textboxAddress = new() { Margin = new Thickness(2) };
Grid.SetRow(textboxAddress, 1);
Grid.SetColumn(textboxAddress, 1);
container.Children.Add(textboxAddress);

// Create the two buttons, assign both to the third row and
// assign the second button to the second column.
Button buttonReset = new() { Margin = new Thickness(2), Content = "Reset" };
Grid.SetRow(buttonReset, 2);
container.Children.Add(buttonReset);

Button buttonSubmit = new() { Margin = new Thickness(2), Content = "Submit" };
Grid.SetColumn(buttonSubmit, 1);
Grid.SetRow(buttonSubmit, 2);
container.Children.Add(buttonSubmit);

// Create the popup window and assign the container (Grid) as its content
Window inputWindow = new()
{
    Title = "Input Record",
    Height = double.NaN,
    Width = 300,
    SizeToContent = SizeToContent.Height,
    Content = container
};

inputWindow.Show();
' Grid container which is the content of the Window
Dim container As New Grid() With {.Margin = New Thickness(5)}
container.RowDefinitions.Add(New RowDefinition())
container.RowDefinitions.Add(New RowDefinition())
container.RowDefinitions.Add(New RowDefinition())
container.ColumnDefinitions.Add(New ColumnDefinition())
container.ColumnDefinitions.Add(New ColumnDefinition())

' Create the two labels, assign the second label to the second row
Dim labelName As New Label() With {.Content = "Enter your name:"}
container.Children.Add(labelName)

Dim labelAddress As New Label() With {.Content = "Enter your address:"}
Grid.SetRow(labelAddress, 1)
container.Children.Add(labelAddress)

' Create the two textboxes, assign both to the second column and
' assign the second textbox to the second row.
Dim textboxName As New TextBox() With {.Margin = New Thickness(2)}
Grid.SetColumn(textboxName, 1)
container.Children.Add(textboxName)

Dim textboxAddress As New TextBox() With {.Margin = New Thickness(2)}
Grid.SetRow(textboxAddress, 1)
Grid.SetColumn(textboxAddress, 1)
container.Children.Add(textboxAddress)

' Create the two buttons, assign both to the third row and
' assign the second button to the second column.
Dim buttonReset As New Button() With {.Margin = New Thickness(2), .Content = "Reset"}
Grid.SetRow(buttonReset, 2)
container.Children.Add(buttonReset)

Dim buttonSubmit As New Button() With {.Margin = New Thickness(2), .Content = "Submit"}
Grid.SetColumn(buttonSubmit, 1)
Grid.SetRow(buttonSubmit, 2)
container.Children.Add(buttonSubmit)

' Create the window and assign the container (Grid) as its content
Dim inputWindow As New Window() With
{
    .Title = "Input Record",
    .Height = Double.NaN,
    .Width = 300,
    .SizeToContent = SizeToContent.Height,
    .Content = container
}

inputWindow.Show()

S’abonner à des événements

Vous pouvez vous abonner à l’événement d’un contrôle à l’aide de XAML ou de code, mais vous ne pouvez gérer qu’un événement dans le code.

En XAML, l’événement est défini en tant qu’attribut sur l’élément. Vous ne pouvez pas utiliser la <Element.Event>handler<Element.Event> notation pour les événements. L’extrait de code suivant montre comment s’abonner à l’événement Click d’un Button:

<Button Click="Submit_Click" Grid.Row="2" Grid.Column="1" Name="Submit" Margin="2">Submit</Button>

Et voici comment procéder de la même façon dans le code :

Button buttonSubmit = new() { Margin = new Thickness(2), Content = "Submit" };
buttonSubmit.Click += Submit_Click;
Dim buttonSubmit As New Button() With {.Margin = New Thickness(2), .Content = "Submit"}
AddHandler buttonSubmit.Click, AddressOf Submit_Click

L’extrait de code suivant gère l’événement Click d’un Button:

private void Submit_Click(object sender, RoutedEventArgs e)
{
    MessageBox.Show("Someone clicked the submit button.");
}
Private Sub Submit_Click(sender As Object, e As Windows.RoutedEventArgs)
    MessageBox.Show("Someone clicked the submit button.")
End Sub

Modifier l’apparence d’un contrôle

Il est courant de modifier l’apparence d’un contrôle pour qu’il corresponde à l’apparence de votre application. Vous pouvez modifier l’apparence d’un contrôle en effectuant l’une des opérations suivantes, en fonction de ce que vous souhaitez accomplir :

  • Modifiez la valeur d’une propriété du contrôle.
  • Créez un espace Style pour le contrôle.
  • Créez un nouvel élément ControlTemplate pour le contrôle.

Modifier la propriété d’un contrôle

De nombreux contrôles ont des propriétés qui vous permettent de modifier l’apparence du contrôle, comme l’arrière-plan d’un bouton. Vous pouvez définir les propriétés de valeur dans XAML et dans le code. L’exemple suivant définit les propriétés Background, FontSize, et FontWeight d’un Button dans XAML :

<Button Grid.Row="2" Grid.Column="1" Name="Submit" Margin="2" Content="Submit">
    <Button.FontSize>18</Button.FontSize>
    <Button.FontWeight>Bold</Button.FontWeight>
    <Button.Background>
        <LinearGradientBrush>
            <GradientStop Color="#0073E6" Offset="0.0" />
            <GradientStop Color="#81D4FA" Offset="0.9" />
        </LinearGradientBrush>
    </Button.Background>
</Button>

Et voici comment procéder de la même façon dans le code :

Button buttonSubmit = new() { Margin = new Thickness(2), Content = "Submit" };
buttonSubmit.FontSize = 18f;
buttonSubmit.FontWeight = FontWeights.Bold;
buttonSubmit.Background =
    new LinearGradientBrush(
        (Color)ColorConverter.ConvertFromString("#0073E6"),
        (Color)ColorConverter.ConvertFromString("#81D4FA"),
        new Point(0d, 0d),
        new Point(0.9d, 0d));
Dim buttonSubmit As New Button() With {.Margin = New Thickness(2), .Content = "Submit"}
buttonSubmit.FontSize = 18.0F
buttonSubmit.FontWeight = FontWeights.Bold
buttonSubmit.Background =
        New LinearGradientBrush(
            ColorConverter.ConvertFromString("#0073E6"),
            ColorConverter.ConvertFromString("#81D4FA"),
            New Point(0D, 0D),
            New Point(0.9D, 0D))

L’exemple de fenêtre ressemble maintenant à l’image suivante :

Capture d’écran d’une application WPF avec deux zones de texte étiquetées nom et adresse. Deux boutons sont visibles. Un bouton est nommé « Réinitialiser » et l’autre « Submit ». Le bouton « Envoyer » a un arrière-plan dégradé qui passe d’un bleu à un bleu plus clair.

Créer un style pour un contrôle

WPF vous offre une capacité étendue à spécifier l’apparence des contrôles en créant un Style, au lieu de définir des propriétés sur chaque contrôle. Style Les définitions sont habituellement établies en XAML dans un ResourceDictionary, par exemple dans la propriété Resources d’un contrôle ou d’une fenêtre. Les ressources sont appliquées au domaine où elles sont déclarées. Pour plus d’informations, consultez Vue d’ensemble des ressources XAML.

L’exemple suivant applique un Style à chaque Button contenu dans le même Grid qui définit le style :

<Grid.Resources>
    <Style TargetType="{x:Type Button}">
        <Style.Setters>
            <Setter Property="FontSize" Value="18" />
            <Setter Property="FontWeight" Value="Bold" />
            <Setter Property="Background">
                <Setter.Value>
                    <LinearGradientBrush>
                        <GradientStop Color="#0073E6" Offset="0.0" />
                        <GradientStop Color="#81D4FA" Offset="0.9" />
                    </LinearGradientBrush>
                </Setter.Value>
            </Setter>
        </Style.Setters>
    </Style>
</Grid.Resources>

Et voici comment procéder de la même façon dans le code :

Grid container = new() { Margin = new Thickness(5) };
container.RowDefinitions.Add(new RowDefinition());
container.RowDefinitions.Add(new RowDefinition());
container.RowDefinitions.Add(new RowDefinition());
container.ColumnDefinitions.Add(new ColumnDefinition());
container.ColumnDefinitions.Add(new ColumnDefinition());

Style buttonStyle = new(typeof(Button));
buttonStyle.Setters.Add(new Setter(Button.FontSizeProperty, 18d));
buttonStyle.Setters.Add(new Setter(Button.FontWeightProperty, FontWeights.Bold));
buttonStyle.Setters.Add(new Setter(Button.BackgroundProperty,
    new LinearGradientBrush(
        (Color)ColorConverter.ConvertFromString("#0073E6"),
        (Color)ColorConverter.ConvertFromString("#81D4FA"),
        new Point(0d, 0d),
        new Point(0.9d, 0d))));

container.Resources.Add(typeof(Button), buttonStyle);
Dim container As New Grid() With {.Margin = New Thickness(5)}
container.RowDefinitions.Add(New RowDefinition())
container.RowDefinitions.Add(New RowDefinition())
container.RowDefinitions.Add(New RowDefinition())
container.ColumnDefinitions.Add(New ColumnDefinition())
container.ColumnDefinitions.Add(New ColumnDefinition())

Dim buttonStyle As New Style(GetType(Button))
buttonStyle.Setters.Add(New Setter(Button.FontSizeProperty, 18.0R))
buttonStyle.Setters.Add(New Setter(Button.FontWeightProperty, FontWeights.Bold))
buttonStyle.Setters.Add(New Setter(Button.BackgroundProperty,
        New LinearGradientBrush(
            ColorConverter.ConvertFromString("#0073E6"),
            ColorConverter.ConvertFromString("#81D4FA"),
            New Point(0D, 0D),
            New Point(0.9D, 0D))))

container.Resources.Add(GetType(Button), buttonStyle)

L’image suivante montre le style appliqué à la grille de la fenêtre, qui modifie l’apparence des deux boutons :

Capture d’écran d’une application WPF avec deux zones de texte étiquetées nom et adresse. Deux boutons sont visibles. Un bouton est nommé « Réinitialiser » et l’autre « Submit ». Les deux boutons présentent un arrière-plan dégradé qui passe d’un bleu à un bleu plus clair.

Au lieu d’appliquer le style à tous les contrôles d’un type spécifique, ils peuvent également être affectés à des contrôles spécifiques en ajoutant une clé au style dans le dictionnaire de ressources et en référençant cette clé dans la Style propriété du contrôle. Pour plus d’informations sur les styles, consultez Style et Création de modèles.

Créer un ControlTemplate

A Style vous permet de définir des propriétés sur plusieurs contrôles à la fois, mais parfois vous souhaiterez peut-être personnaliser l’apparence d’un contrôle au-delà de ce que vous pouvez faire avec un Style. Les classes qui héritent de la Control classe ont un ControlTemplate, qui définit la structure et l’apparence d’un contrôle.

Considérez le Button contrôle, un contrôle courant utilisé par presque toutes les applications. Le comportement principal d’un bouton consiste à permettre à une application d’effectuer une action lorsque l’utilisateur sélectionne le bouton. Par défaut, le bouton dans WPF apparaît comme un rectangle surélevé. Lors du développement d’une application, vous souhaiterez peut-être tirer parti du comportement d’un bouton, c’est-à-dire de la façon dont l’utilisateur interagit avec le bouton, ce qui déclenche un Click événement, mais vous pouvez modifier l’apparence du bouton au-delà de ce que vous pouvez faire en modifiant les propriétés du bouton. Dans ce cas, vous pouvez créer un nouveau ControlTemplate.

L’exemple suivant crée un ControlTemplate pour un Button. Le ControlTemplate crée un visuel pour le Button qui présente une bordure avec des bords arrondis et un arrière-plan dégradé.

<Button Grid.Row="2" Grid.Column="1" Name="Submit" Margin="2" Content="Submit">
    <Button.Template>
        <ControlTemplate TargetType="Button">
            <Border Name="Border" CornerRadius="10" BorderThickness="1" BorderBrush="Black">
                <Border.Background>
                    <LinearGradientBrush StartPoint="0,0.5" 
                         EndPoint="1,0.5">
                        <GradientStop Color="{Binding Background.Color, RelativeSource={RelativeSource TemplatedParent}}" Offset="0.0" />
                        <GradientStop Color="PeachPuff" Offset="0.9" />
                    </LinearGradientBrush>
                </Border.Background>
                <ContentPresenter Margin="2" HorizontalAlignment="Center" VerticalAlignment="Center" RecognizesAccessKey="True"/>
            </Border>
            <ControlTemplate.Triggers>
                <!--Change the appearance of the button when the user clicks it.-->
                <Trigger Property="IsPressed" Value="true">
                    <Setter TargetName="Border" Property="Background">
                        <Setter.Value>
                            <LinearGradientBrush StartPoint="0,0.5" EndPoint="1,0.5">
                                <GradientStop Color="{Binding Background.Color, RelativeSource={RelativeSource TemplatedParent}}" Offset="0.0" />
                                <GradientStop Color="LightBlue" Offset="0.9" />
                            </LinearGradientBrush>
                        </Setter.Value>
                    </Setter>
                </Trigger>
            </ControlTemplate.Triggers>
        </ControlTemplate>
    </Button.Template>
</Button>

Remarque

La propriété Background de Button doit être définie sur un SolidColorBrush pour que l'exemple fonctionne correctement.

Et voici comment faire de même dans le code. Le code suivant crée une chaîne XAML et l’analyse pour générer un modèle qui peut être appliqué, qui est la méthode prise en charge pour générer un modèle au moment de l’exécution.

Button buttonSubmit = new() { Margin = new Thickness(2), Content = "Submit" };

// Create the XAML used to define the button template
const string xaml = """
    <ControlTemplate TargetType="Button">
        <Border Name="Border" CornerRadius="10" BorderThickness="1" BorderBrush="Black">
            <Border.Background>
                <LinearGradientBrush StartPoint="0,0.5" 
                     EndPoint="1,0.5">
                    <GradientStop Color="{Binding Background.Color, RelativeSource={RelativeSource TemplatedParent}}" Offset="0.0" />
                    <GradientStop Color="PeachPuff" Offset="0.9" />
                </LinearGradientBrush>
            </Border.Background>
            <ContentPresenter Margin="2" HorizontalAlignment="Center" VerticalAlignment="Center" RecognizesAccessKey="True"/>
        </Border>
        <ControlTemplate.Triggers>
            <!--Change the appearance of the button when the user clicks it.-->
            <Trigger Property="IsPressed" Value="true">
                <Setter TargetName="Border" Property="Background">
                    <Setter.Value>
                        <LinearGradientBrush StartPoint="0,0.5" EndPoint="1,0.5">
                            <GradientStop Color="{Binding Background.Color, RelativeSource={RelativeSource TemplatedParent}}" Offset="0.0" />
                            <GradientStop Color="LightBlue" Offset="0.9" />
                        </LinearGradientBrush>
                    </Setter.Value>
                </Setter>
            </Trigger>
        </ControlTemplate.Triggers>
    </ControlTemplate>
    """;

// Load the XAML into a stream that can be parsed
using MemoryStream stream = new(System.Text.Encoding.UTF8.GetBytes(xaml));

// Create a parser context and add the default namespace and 
// the x namespace, which is common to WPF XAML
System.Windows.Markup.ParserContext context = new();
context.XmlnsDictionary.Add("", "http://schemas.microsoft.com/winfx/2006/xaml/presentation");
context.XmlnsDictionary.Add("x", "http://schemas.microsoft.com/winfx/2006/xaml");

// Parse the XAML and assign it to the button's template
buttonSubmit.Template = (ControlTemplate)System.Windows.Markup.XamlReader.Load(stream, context);

// Set the other properties of the button
Grid.SetColumn(buttonSubmit, 1);
Grid.SetRow(buttonSubmit, 2);

// Assign the button to the grid container
container.Children.Add(buttonSubmit);
Dim buttonSubmit As New Button() With {.Margin = New Thickness(2), .Content = "Submit"}

' Create the XAML used to define the button template
Const xaml As String = "
    <ControlTemplate TargetType=""Button"">
        <Border Name=""Border"" CornerRadius=""10"" BorderThickness=""1"" BorderBrush=""Black"">
            <Border.Background>
                <LinearGradientBrush StartPoint=""0,0.5"" 
                     EndPoint=""1,0.5"">
                    <GradientStop Color=""{Binding Background.Color, RelativeSource={RelativeSource TemplatedParent}}"" Offset=""0.0"" />
                    <GradientStop Color=""PeachPuff"" Offset=""0.9"" />
                </LinearGradientBrush>
            </Border.Background>
            <ContentPresenter Margin=""2"" HorizontalAlignment=""Center"" VerticalAlignment=""Center"" RecognizesAccessKey=""True""/>
        </Border>
        <ControlTemplate.Triggers>
            <!--Change the appearance of the button when the user clicks it.-->
            <Trigger Property=""IsPressed"" Value=""true"">
                <Setter TargetName=""Border"" Property=""Background"">
                    <Setter.Value>
                        <LinearGradientBrush StartPoint=""0,0.5"" EndPoint=""1,0.5"">
                            <GradientStop Color=""{Binding Background.Color, RelativeSource={RelativeSource TemplatedParent}}"" Offset=""0.0"" />
                            <GradientStop Color=""LightBlue"" Offset=""0.9"" />
                        </LinearGradientBrush>
                    </Setter.Value>
                </Setter>
            </Trigger>
        </ControlTemplate.Triggers>
    </ControlTemplate>"

' Load the XAML into a stream that can be parsed
Using stream As New MemoryStream(System.Text.Encoding.UTF8.GetBytes(xaml))

    ' Create a parser context and add the default namespace and 
    ' the x namespace, which is common to WPF XAML
    Dim context = New System.Windows.Markup.ParserContext()
    context.XmlnsDictionary.Add("", "http://schemas.microsoft.com/winfx/2006/xaml/presentation")
    context.XmlnsDictionary.Add("x", "http://schemas.microsoft.com/winfx/2006/xaml")

    ' Parse the XAML and assign it to the button's template
    buttonSubmit.Template = System.Windows.Markup.XamlReader.Load(stream, context)
End Using

' Set the other properties of the button
Grid.SetColumn(buttonSubmit, 1)
Grid.SetRow(buttonSubmit, 2)

' Assign the button to the grid container
container.Children.Add(buttonSubmit)

L’image suivante montre à quoi ressemble le modèle lorsqu’il est appliqué :

Capture d’écran d’une application WPF avec deux zones de texte étiquetées nom et adresse. Deux boutons sont visibles. Un bouton est nommé « Réinitialiser » et l’autre « Submit ». Le bouton « Envoyer » comporte des angles arrondis et une couleur de pêche lui est appliquée.

Dans l'exemple précédent, le style ControlTemplate est appliqué à un seul bouton. Toutefois, un ControlTemplate peut être affecté à un Style bouton et appliqué à tous les boutons, comme ce qui a été démontré dans la section Créer un style pour une section de contrôle .

Pour plus d’informations sur la façon de tirer parti des fonctionnalités uniques fournies par un modèle, consultez Style et Création de modèles.

Contenu enrichi dans les contrôles

La plupart des classes qui héritent de la Control classe ont la capacité de contenir du contenu enrichi. Par exemple, un Label peut contenir n’importe quel objet, tel qu’une chaîne, un Imageou un Panel. Les classes suivantes prennent en charge le contenu enrichi et jouent le rôle de classes de base pour la plupart des contrôles dans WPF :