Partager via


Bouton

L’interface utilisateur de l’application multiplateforme .NET (.NET MAUI) Button affiche du texte et répond à un appui ou à un clic qui ordonne à l’application d’effectuer une tâche. Un Button affiche généralement une chaîne de texte courte indiquant une commande, mais elle peut également afficher une image bitmap, ou une combinaison de texte et d’une image. Lorsque vous appuyez ou cliquez sur Button, ce dernier lance cette commande.

Button définit les propriétés suivantes :

  • BorderColor, de type Color, décrit la couleur de bordure du bouton.
  • BorderWidth, de type double, définit la largeur de la bordure du bouton.
  • CharacterSpacing, de type double, définit l’espacement entre les caractères du texte du bouton.
  • Command, de type ICommand, définit la commande exécutée quand l’utilisateur appuie sur le bouton.
  • CommandParameter, de type object, est le paramètre transmis à Command.
  • ContentLayout, de type ButtonContentLayout, définit l’objet qui contrôle la position de l’image du bouton et l’espacement entre l’image et le texte du bouton.
  • CornerRadius, de type int, décrit le rayon d’angle de la bordure du bouton.
  • FontAttributes, de type FontAttributes, détermine le style du texte.
  • FontAutoScalingEnabled, de type bool, définit si le texte du bouton reflète ou non les préférences de mise à l’échelle définies dans le système d’exploitation. La valeur par défaut de cette propriété est true.
  • FontFamily, de type string, définit la famille de police.
  • FontSize, de type double, définit la taille de police.
  • ImageSource, de type ImageSource, spécifie une image bitmap à afficher comme contenu du bouton.
  • LineBreakMode, de type LineBreakMode, détermine comment le texte doit être traité lorsqu’il ne peut pas tenir sur une ligne.
  • Padding, de type Thickness, détermine le remplissage du bouton.
  • Text, de type string, définit le texte affiché comme contenu du bouton.
  • TextColor, de type Color, décrit la couleur du texte du bouton.
  • TextTransform, de type TextTransform, définit la casse du texte du bouton.

Les propriétés s’appuient sur des objets BindableProperty, ce qui signifie qu’elles peuvent être les cibles de liaisons de données et mises en forme avec un style.

Remarque

Même si Button définit une ImageSource propriété, qui vous permet d’afficher une image sur le Button, cette propriété est destinée à être utilisée lors de l’affichage d’une petite icône en regard du Button texte.

En outre, Button définit des événements Clicked, Pressed et Released. L’événement Clicked est déclenché quand un appui sur Button avec un doigt ou un pointeur de souris est libéré de la surface du bouton. L’événement Pressed est déclenché quand un doigt appuie sur un Button ou quand un bouton de souris est appuyé avec le pointeur positionné sur Button. L’événement Released est déclenché quand le doigt ou le bouton de souris est libéré. En règle générale, un événement Clicked est également déclenché en même temps que l’événement Released, mais si le doigt ou le pointeur de souris s’éloigne de la surface du Button avant d’être libéré, il est possible que l’événement Clicked ne se produise pas.

Important

La propriété d’un Button doit IsEnabled être définie sur true pour qu’il réponde aux appuis.

Créer un bouton

Pour créer un bouton, créez un objet Button et gérez son événement Clicked.

L’exemple XAML suivant montre comment créer une Button :

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="ButtonDemos.BasicButtonClickPage"
             Title="Basic Button Click">
    <StackLayout>
        <Button Text="Click to Rotate Text!"
                VerticalOptions="Center"
                HorizontalOptions="Center"
                Clicked="OnButtonClicked" />
        <Label x:Name="label"
               Text="Click the Button above"
               FontSize="18"
               VerticalOptions="Center"
               HorizontalOptions="Center" />
    </StackLayout>
</ContentPage>

La propriété Text spécifie le texte qui apparaît dans l’élément Button. L’événement Clicked est défini sur un gestionnaire d’événements nommé OnButtonClicked. Ce gestionnaire d’événements se trouve dans le fichier code-behind :

public partial class BasicButtonClickPage : ContentPage
{
    public BasicButtonClickPage ()
    {
        InitializeComponent ();
    }

    async void OnButtonClicked(object sender, EventArgs args)
    {
        await label.RelRotateTo(360, 1000);
    }
}

Dans cet exemple, quand le Button est pressé, la méthode OnButtonClicked s’exécute. L’argument sender est l’objet Button responsable de cet événement. Vous pouvez l’utiliser pour accéder à l’objet Button ou pour faire la distinction entre plusieurs objets Button qui partagent le même événement Clicked. Le gestionnaire Clicked appelle une fonction d’animation qui fait pivoter le Label de 360 degrés en 1000 millisecondes :

Capture d’écran d’un bouton.

Le code C# équivalent pour créer un Button est :

Button button = new Button
{
    Text = "Click to Rotate Text!",
    VerticalOptions = LayoutOptions.Center,
    HorizontalOptions = LayoutOptions.Center
};
button.Clicked += async (sender, args) => await label.RelRotateTo(360, 1000);

Utiliser l’interface de commande

Une application peut répondre aux appuis de Button sans gérer l’événement Clicked. Elle Button implémente un autre mécanisme de notification appelé interface de commande ou d’exécution de commandes. Cette opération comprend deux propriétés :

Cette approche est particulièrement adaptée à la liaison de données, et en particulier lors de l’implémentation du modèle Model-View-ViewModel (MVVM). Dans une application MVVM, le viewmodel définit les propriétés de type ICommand qui sont ensuite connectées à des objets Button avec des liaisons de données. .NET MAUI définit également des classes Command et Command<T> qui implémentent l’interface ICommand et aident le viewmodel à définir des propriétés de type ICommand. Pour plus d’informations sur les commandes, consultez Commandes.

L’exemple suivant montre une classe viewmodel très simple qui définit une propriété de type double nommée Number, et deux propriétés de type ICommand nommées MultiplyBy2Command et DivideBy2Command :

public class CommandDemoViewModel : INotifyPropertyChanged
{
    double number = 1;

    public event PropertyChangedEventHandler PropertyChanged;

    public ICommand MultiplyBy2Command { get; private set; }
    public ICommand DivideBy2Command { get; private set; }

    public CommandDemoViewModel()
    {
        MultiplyBy2Command = new Command(() => Number *= 2);
        DivideBy2Command = new Command(() => Number /= 2);
    }

    public double Number
    {
        get
        {
            return number;
        }
        set
        {
            if (number != value)
            {
                number = value;
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Number"));
            }
        }
    }
}

Dans cet exemple, les deux propriétés ICommand sont initialisées dans le constructeur de la classe avec deux objets de type Command. Les Command constructeurs incluent une petite fonction (appelée argument du execute constructeur) qui double ou réduit de moitié la valeur de la Number propriété.

L’exemple XAML suivant consomme la classe CommandDemoViewModel :

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:ButtonDemos"
             x:Class="ButtonDemos.BasicButtonCommandPage"
             Title="Basic Button Command">
    <ContentPage.BindingContext>
        <local:CommandDemoViewModel />
    </ContentPage.BindingContext>

    <StackLayout>
        <Label Text="{Binding Number, StringFormat='Value is now {0}'}"
               FontSize="18"
               VerticalOptions="Center"
               HorizontalOptions="Center" />
        <Button Text="Multiply by 2"
                VerticalOptions="Center"
                HorizontalOptions="Center"
                Command="{Binding MultiplyBy2Command}" />
        <Button Text="Divide by 2"
                VerticalOptions="Center"
                HorizontalOptions="Center"
                Command="{Binding DivideBy2Command}" />
    </StackLayout>
</ContentPage>

Dans cet exemple, l’élément Label et deux objets Button contiennent des liaisons aux trois propriétés de la classe CommandDemoViewModel. À mesure que les deux objets Button sont appuyés, les commandes sont exécutées et le nombre change de valeur. L’avantage de cette approche par rapport aux gestionnaires Clicked est que toute la logique impliquant la fonctionnalité de cette page se trouve dans le viewmodel plutôt que dans le fichier code-behind, ce qui permet de mieux séparer l’interface utilisateur de la logique métier.

Il est également possible que les objets Command contrôlent l’activation et la désactivation des objets Button. Par exemple, supposons que vous souhaitiez limiter la plage de valeurs numériques comprises entre 210 et 2 à 10. Vous pouvez ajouter une autre fonction au constructeur (appelé l’argument canExecute) qui retourne true si le Button doit être activé :

public class CommandDemoViewModel : INotifyPropertyChanged
{
    ···
    public CommandDemoViewModel()
    {
        MultiplyBy2Command = new Command(
            execute: () =>
            {
                Number *= 2;
                ((Command)MultiplyBy2Command).ChangeCanExecute();
                ((Command)DivideBy2Command).ChangeCanExecute();
            },
            canExecute: () => Number < Math.Pow(2, 10));

        DivideBy2Command = new Command(
            execute: () =>
            {
                Number /= 2;
                ((Command)MultiplyBy2Command).ChangeCanExecute();
                ((Command)DivideBy2Command).ChangeCanExecute();
            },
            canExecute: () => Number > Math.Pow(2, -10));
    }
    ···
}

Dans cet exemple, les appels à la méthode ChangeCanExecute de Command sont requis afin que la méthode Command puisse appeler la méthode canExecute et déterminer si le Button doit être désactivé ou non. Avec ce changement de code, à mesure que le nombre atteint la limite, le Button est désactivé.

Il est également possible que deux éléments Button ou plus soient liés à la même propriété ICommand. Les éléments Button peuvent être distingués à l’aide de la propriété CommandParameter de Button. Dans ce cas, vous souhaiterez utiliser la classe Command<T> générique. L’objet CommandParameter est ensuite passé en tant qu’argument aux méthodes execute et canExecute. Pour plus d’informations, consultez Exécution de commandes.

Appuyez sur le bouton et relâchez

L’événement Pressed est déclenché quand un doigt appuie sur un Button ou quand un bouton de souris est appuyé avec le pointeur positionné sur Button. L’événement Released est déclenché quand le doigt ou le bouton de souris est libéré. En règle générale, un événement Clicked est également déclenché en même temps que l’événement Released, mais si le doigt ou le pointeur de souris s’éloigne de la surface du Button avant d’être libéré, il est possible que l’événement Clicked ne se produise pas.

L’exemple XAML suivant montre un Label et un Button avec des gestionnaires attachés aux événements Pressed et Released :

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="ButtonDemos.PressAndReleaseButtonPage"
             Title="Press and Release Button">
    <StackLayout>
        <Button Text="Press to Rotate Text!"
                VerticalOptions="Center"
                HorizontalOptions="Center"
                Pressed="OnButtonPressed"
                Released="OnButtonReleased" />
        <Label x:Name="label"
               Text="Press and hold the Button above"
               FontSize="18"
               VerticalOptions="Center"
               HorizontalOptions="Center" />
    </StackLayout>
</ContentPage>

Le fichier code-behind anime le Label lorsqu’un événement Pressed se produit, mais suspend la rotation lorsqu’un événement Released se produit :

public partial class PressAndReleaseButtonPage : ContentPage
{
    IDispatcherTimer timer;
    Stopwatch stopwatch = new Stopwatch();

    public PressAndReleaseButtonPage()
    {
        InitializeComponent();

        timer = Dispatcher.CreateTimer();
        timer.Interval = TimeSpan.FromMilliseconds(16);
        timer.Tick += (s, e) =>
        {
            label.Rotation = 360 * (stopwatch.Elapsed.TotalSeconds % 1);
        };
    }

    void OnButtonPressed(object sender, EventArgs args)
    {
        stopwatch.Start();
        timer.Start();
    }

    void OnButtonReleased(object sender, EventArgs args)
    {
        stopwatch.Stop();
        timer.Stop();
    }
}

Le résultat est que le Label pivote uniquement lorsqu’un doigt est en contact avec le Button, et s’arrête lorsque le doigt est relâché.

États visuels de Button

Button a un Pressed VisualState qui peut être utilisé pour initier une modification visuelle au Button une fois appuyé, s’il est activé.

L’exemple de XAML suivant montre comment définir un état visuel pour l’état Pressed :

<Button Text="Click me!"
        ...>
    <VisualStateManager.VisualStateGroups>
        <VisualStateGroupList>
            <VisualStateGroup x:Name="CommonStates">
                <VisualState x:Name="Normal">
                    <VisualState.Setters>
                        <Setter Property="Scale"
                                Value="1" />
                    </VisualState.Setters>
                </VisualState>
                <VisualState x:Name="Pressed">
                    <VisualState.Setters>
                        <Setter Property="Scale"
                                Value="0.8" />
                    </VisualState.Setters>
                </VisualState>
                <VisualState x:Name="PointerOver" />            
            </VisualStateGroup>
        </VisualStateGroupList>
    </VisualStateManager.VisualStateGroups>
</Button>

Dans cet exemple, l’état Pressed VisualState spécifie que lorsque le Button est appuyé, sa propriété Scale est modifiée en remplaçant la valeur par défaut de 1 par 0,8. L’élément Normal VisualState spécifie que lorsque le Button est dans un état normal, sa propriété Scale est définie sur 1. Par conséquent, l’effet global est que lorsque le Button est appuyé, il est remis à une échelle afin d’être légèrement plus petit, et quand le Button est libéré, il est remis à sa taille par défaut.

Important

Pour qu’un Button retourne à son état Normal, le VisualStateGroup doit également définir un état de PointerOver. Si vous utilisez les styles du ResourceDictionary créés par le modèle de projet d’application .NET MAUI, vous aurez déjà un style implicite de Button qui définit l’état de PointerOver.

Pour plus d’informations sur les états visuels, consultez États visuels.

Utiliser des bitmaps avec des boutons

La Button classe définit une propriété qui vous permet d’afficher ImageSource une petite image bitmap sur le , seul ou en combinaison avec du Buttontexte. Vous pouvez également spécifier la façon dont le texte et l’image sont organisés. La propriété ImageSource est de type ImageSource, ce qui signifie que les bitmaps peuvent être chargés à partir d’un fichier, d’une ressource intégrée, d’une URI ou d’un flux.

Les bitmaps ne sont pas mis à l’échelle pour s’adapter à un Button. La meilleure taille est généralement comprise entre 32 et 64 unités indépendantes de l’appareil, selon la taille à laquelle que vous souhaitez pour le bitmap.

Vous pouvez spécifier la façon dont les propriétés Text et ImageSource sont organisées sur le Button à l’aide de la propriété ContentLayout de Button. Cette propriété est de type ButtonContentLayout, et son constructeur a deux arguments :

  • Un membre de l’énumération ImagePosition : Left, Top, ou Right Bottom indiquant comment l’image bitmap apparaît par rapport au texte.
  • Une valeur double de l’espacement entre le bitmap et le texte.

En XAML, vous pouvez créer un Button et définir la propriété ContentLayout en spécifiant uniquement le membre d’énumération, ou l’espacement, ou les deux dans n’importe quel ordre séparé par des virgules :

<Button Text="Button text"
        ImageSource="button.png"
        ContentLayout="Right, 20" />

Le code C# équivalent est :

Button button = new Button
{
    Text = "Button text",
    ImageSource = new FileImageSource
    {
        File = "button.png"
    },
    ContentLayout = new Button.ButtonContentLayout(Button.ButtonContentLayout.ImagePosition.Right, 20)
};

Remarque

Si un Button texte contient du texte et une image, il peut ne pas être possible d’ajuster tout le contenu à l’intérieur du bouton. Vous devez donc dimensionner votre image manuellement pour atteindre votre disposition souhaitée.

Désactiver un bouton

Une application entre parfois dans un état dans lequel un clic sur un Button n’est pas une opération valide. Dans ce cas, vous pouvez désactiver le Button en définissant sa propriété IsEnabled sur false.