Xamarin.Forms Bouton

Télécharger l’exemple Télécharger l’exemple

Le bouton répond à un clic qui indique à une application d’effectuer une tâche particulière.

Le Button est le contrôle interactif le plus fondamental dans l’ensemble de Xamarin.Forms. Le Button affiche généralement une chaîne de texte courte indiquant une commande, mais il peut également afficher une image bitmap ou une combinaison de texte et d’une image. L’utilisateur appuie sur avec Button un doigt ou clique dessus avec une souris pour lancer cette commande.

La plupart des sujets abordés ci-dessous correspondent à des pages de l’exemple ButtonDemos .

Gestion des clics sur les boutons

Button définit un Clicked événement déclenché lorsque l’utilisateur appuie sur avec Button un doigt ou un pointeur de souris. L’événement est déclenché lorsque le doigt ou le bouton de la souris est libéré de la surface du Button. Button Sa propriété doit être IsEnabled définie sur true pour qu’elle réponde aux pressions.

La page Clic sur le bouton de base de l’exemple ButtonDemos montre comment instancier un Button dans XAML et gérer son Clicked événement. Le fichier BasicButtonClickPage.xaml contient un StackLayout avec à la fois un Label et un Button:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="ButtonDemos.BasicButtonClickPage"
             Title="Basic Button Click">
    <StackLayout>

        <Label x:Name="label"
               Text="Click the Button below"
               FontSize="Large"
               VerticalOptions="CenterAndExpand"
               HorizontalOptions="Center" />

        <Button Text="Click to Rotate Text!"
                VerticalOptions="CenterAndExpand"
                HorizontalOptions="Center"
                Clicked="OnButtonClicked" />

    </StackLayout>
</ContentPage>

Le Button a tendance à occuper tout l’espace qui lui est autorisé. Par exemple, si vous ne définissez pas la HorizontalOptions propriété de Button sur autre chose que Fill, le Button occupera toute la largeur de son parent.

Par défaut, le Button est rectangulaire, mais vous pouvez lui donner des coins arrondis à l’aide de la CornerRadius propriété, comme décrit ci-dessous dans la section Apparence du bouton.

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 se trouve dans le fichier code-behind , BasicButtonClickPage.xaml.cs :

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

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

Lorsque vous appuyez sur Button, 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 Button objets partageant le même Clicked événement.

Ce gestionnaire particulier Clicked appelle une fonction d’animation qui fait pivoter les Label 360 degrés en 1 000 millisecondes. Voici le programme en cours d’exécution sur les appareils iOS et Android, et en tant qu’application plateforme Windows universelle (UWP) sur le bureau Windows 10 :

le bouton De base Cliquez sur

Notez que la OnButtonClicked méthode inclut le async modificateur, car await est utilisé dans le gestionnaire d’événements. Un Clicked gestionnaire d’événements nécessite le async modificateur uniquement si le corps du gestionnaire utilise await.

Chaque plateforme affiche le Button de sa propre manière. Dans la section Apparence du bouton , vous verrez comment définir des couleurs et rendre la Button bordure visible pour des apparences plus personnalisées. Button implémente l’interface IFontElement , de sorte qu’elle inclut les FontFamilypropriétés , FontSizeet FontAttributes .

Création d’un bouton dans le code

Il est courant d’instancier un Button en XAML, mais vous pouvez également créer un Button dans le code. Cela peut être pratique lorsque votre application doit créer plusieurs boutons basés sur des données énumérables avec une foreach boucle.

La page Clic sur le bouton code montre comment créer une page qui est fonctionnellement équivalente à la page Clic sur le bouton de base , mais entièrement en C# :

public class CodeButtonClickPage : ContentPage
{
    public CodeButtonClickPage ()
    {
        Title = "Code Button Click";

        Label label = new Label
        {
            Text = "Click the Button below",
            FontSize = Device.GetNamedSize(NamedSize.Large, typeof(Label)),
            VerticalOptions = LayoutOptions.CenterAndExpand,
            HorizontalOptions = LayoutOptions.Center
        };

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

        Content = new StackLayout
        {
            Children =
            {
                label,
                button
            }
        };
    }
}

Tout est effectué dans le constructeur de la classe. Étant donné que le Clicked gestionnaire ne contient qu’une seule instruction, il peut être attaché à l’événement très simplement :

button.Clicked += async (sender, args) => await label.RelRotateTo(360, 1000);

Bien sûr, vous pouvez également définir le gestionnaire d’événements en tant que méthode distincte (tout comme la OnButtonClick méthode dans Clic de bouton de base) et attacher cette méthode à l’événement :

button.Clicked += OnButtonClicked;

Désactivation du bouton

Parfois, une application se trouve dans un état particulier où un clic particulier Button n’est pas une opération valide. Dans ce cas, le Button doit être désactivé en définissant sa IsEnabled propriété sur false. L’exemple classique est un Entry contrôle pour un nom de fichier accompagné d’un fichier ouvert Button: ne Button doit être activé que si du texte a été tapé dans le Entry. Vous pouvez utiliser un DataTrigger pour cette tâche, comme indiqué dans l’article Déclencheurs de données .

Utilisation de l’interface de commande

Il est possible pour une application de répondre aux Button pressions sans gérer l’événement Clicked . Implémente Button un autre mécanisme de notification appelé la commande ou l’interface de commande . Il se compose de deux propriétés :

Cette approche est particulièrement appropriée pour la liaison de données, en particulier lors de l’implémentation de l’architecture MVVM (Model-ViewModel). Ces rubriques sont abordées dans les articles Liaison de données, De liaisons de données à MVVM et MVVM.

Dans une application MVVM, le viewmodel définit des propriétés de type ICommand qui sont ensuite connectées aux éléments XAML Button avec des liaisons de données. Xamarin.Forms définit Command également les classes et Command<T> qui implémentent l’interface ICommand et aident le viewmodel à définir des propriétés de type ICommand.

La commande est décrite plus en détail dans l’article L’interface de commande , mais la page Commande de bouton de base de l’exemple ButtonDemos montre l’approche de base.

La CommandDemoViewModel classe est un 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:

class CommandDemoViewModel : INotifyPropertyChanged
{
    double number = 1;

    public event PropertyChangedEventHandler PropertyChanged;

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

        DivideBy2Command = new Command(() => Number /= 2);
    }

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

    public ICommand MultiplyBy2Command { private set; get; }

    public ICommand DivideBy2Command { private set; get; }
}

Les deux ICommand propriétés 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 Number propriété.

Le fichier BasicButtonCommand.xaml définit son BindingContext instance de CommandDemoViewModel. L’élément Label et les deux Button éléments contiennent des liaisons aux trois propriétés dans CommandDemoViewModel:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             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="Large"
               VerticalOptions="CenterAndExpand"
               HorizontalOptions="Center" />

        <Button Text="Multiply by 2"
                VerticalOptions="CenterAndExpand"
                HorizontalOptions="Center"
                Command="{Binding MultiplyBy2Command}" />

        <Button Text="Divide by 2"
                VerticalOptions="CenterAndExpand"
                HorizontalOptions="Center"
                Command="{Binding DivideBy2Command}" />
    </StackLayout>
</ContentPage>

Lorsque les deux Button éléments sont appuyés, les commandes sont exécutées et la valeur du nombre change :

Commande de base du bouton De base, commande

L’avantage de cette approche par rapport Clicked aux gestionnaires est que toute la logique impliquant les fonctionnalités 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 pour les Command objets de contrôler l’activation et la Button désactivation des éléments. Par exemple, supposons que vous souhaitiez limiter la plage de valeurs de nombre comprise entre 210 et 2 et 10. Vous pouvez ajouter une autre fonction au constructeur (appelé argument canExecute ) qui retourne true si le Button doit être activé. Voici la modification apportée au CommandDemoViewModel constructeur :

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));
    }
    ···
}

Les appels à la ChangeCanExecute méthode de Command sont nécessaires pour que la Command méthode puisse appeler la canExecute méthode et déterminer si le Button doit être désactivé ou non. Avec ce changement de code, à mesure que le nombre atteint la limite, est Button désactivé :

Commande de bouton de base - Commande

Il est possible que plusieurs Button éléments soient liés à la même ICommand propriété. Les Button éléments peuvent être distingués à l’aide de la CommandParameter propriété de Button. Dans ce cas, vous devez utiliser la classe générique Command<T> . L’objet CommandParameter est ensuite passé en tant qu’argument aux execute méthodes et canExecute . Cette technique est présentée en détail dans la section Commande de base de l’article Interface de commande .

L’exemple ButtonDemos utilise également cette technique dans sa MainPage classe. Le fichier MainPage.xaml contient un Button pour chaque page de l’exemple :

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:ButtonDemos"
             x:Class="ButtonDemos.MainPage"
             Title="Button Demos">
    <ScrollView>
        <FlexLayout Direction="Column"
                    JustifyContent="SpaceEvenly"
                    AlignItems="Center">

            <Button Text="Basic Button Click"
                    Command="{Binding NavigateCommand}"
                    CommandParameter="{x:Type local:BasicButtonClickPage}" />

            <Button Text="Code Button Click"
                    Command="{Binding NavigateCommand}"
                    CommandParameter="{x:Type local:CodeButtonClickPage}" />

            <Button Text="Basic Button Command"
                    Command="{Binding NavigateCommand}"
                    CommandParameter="{x:Type local:BasicButtonCommandPage}" />

            <Button Text="Press and Release Button"
                    Command="{Binding NavigateCommand}"
                    CommandParameter="{x:Type local:PressAndReleaseButtonPage}" />

            <Button Text="Button Appearance"
                    Command="{Binding NavigateCommand}"
                    CommandParameter="{x:Type local:ButtonAppearancePage}" />

            <Button Text="Toggle Button Demo"
                    Command="{Binding NavigateCommand}"
                    CommandParameter="{x:Type local:ToggleButtonDemoPage}" />

            <Button Text="Image Button Demo"
                    Command="{Binding NavigateCommand}"
                    CommandParameter="{x:Type local:ImageButtonDemoPage}" />

        </FlexLayout>
    </ScrollView>
</ContentPage>

Chacune Button a sa Command propriété liée à une propriété nommée NavigateCommand, et est CommandParameter définie sur un objet correspondant à l’une Type des classes de page dans le projet.

Cette NavigateCommand propriété est de type ICommand et est définie dans le fichier code-behind :

public partial class MainPage : ContentPage
{
    public MainPage()
    {
        InitializeComponent();

        NavigateCommand = new Command<Type>(async (Type pageType) =>
        {
            Page page = (Page)Activator.CreateInstance(pageType);
            await Navigation.PushAsync(page);
        });

        BindingContext = this;
    }

    public ICommand NavigateCommand { private set; get; }
}

Le constructeur initialise la NavigateCommand propriété sur un Command<Type> objet, car Type est le type de l’objet CommandParameter défini dans le fichier XAML. Cela signifie que la execute méthode a un argument de type Type qui correspond à cet CommandParameter objet. La fonction instancie la page, puis y accède.

Notez que le constructeur conclut en définissant son BindingContext sur lui-même. Cela est nécessaire pour que les propriétés du fichier XAML se lient à la NavigateCommand propriété .

Appuyer et relâcher le bouton

Outre l’événement Clicked, Button définit également les événements Pressed et Released. L’événement Pressed se produit lorsqu’un doigt appuie sur un Button, ou qu’un bouton de la souris est enfoncé avec le pointeur positionné sur .Button L’événement Released se produit lorsque le bouton du doigt ou de la souris est relâché. En règle générale, un Clicked événement est également déclenché en même temps que l’événement Released , mais si le doigt ou le pointeur de la souris s’éloigne de la surface du Button avant d’être libéré, l’événement Clicked peut ne pas se produire.

Les Pressed événements et Released ne sont pas souvent utilisés, mais ils peuvent être utilisés à des fins spéciales, comme illustré dans la page Bouton Appuyer et libérer . Le fichier XAML contient un Label et un Button avec des gestionnaires joints pour les Pressed événements et Released :

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="ButtonDemos.PressAndReleaseButtonPage"
             Title="Press and Release Button">
    <StackLayout>

        <Label x:Name="label"
               Text="Press and hold the Button below"
               FontSize="Large"
               VerticalOptions="CenterAndExpand"
               HorizontalOptions="Center" />

        <Button Text="Press to Rotate Text!"
                VerticalOptions="CenterAndExpand"
                HorizontalOptions="Center"
                Pressed="OnButtonPressed"
                Released="OnButtonReleased" />

    </StackLayout>
</ContentPage>

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

public partial class PressAndReleaseButtonPage : ContentPage
{
    bool animationInProgress = false;
    Stopwatch stopwatch = new Stopwatch();

    public PressAndReleaseButtonPage ()
    {
        InitializeComponent ();
    }

    void OnButtonPressed(object sender, EventArgs args)
    {
        stopwatch.Start();
        animationInProgress = true;

        Device.StartTimer(TimeSpan.FromMilliseconds(16), () =>
        {
            label.Rotation = 360 * (stopwatch.Elapsed.TotalSeconds % 1);

            return animationInProgress;
        });
    }

    void OnButtonReleased(object sender, EventArgs args)
    {
        animationInProgress = false;
        stopwatch.Stop();
    }
}

Le résultat est que le Label seul pivote pendant qu’un doigt est en contact avec le Button, et s’arrête lorsque le doigt est libéré :

Appuyez sur le bouton Et relâchez

Ce type de comportement a des applications pour les jeux : un doigt tenu sur un Button peut faire déplacer un objet à l’écran dans une direction particulière.

Apparence du bouton

Hérite Button ou définit plusieurs propriétés qui affectent son apparence :

  • TextColor est la couleur du Button texte
  • BackgroundColor est la couleur de l’arrière-plan de ce texte
  • BorderColor est la couleur d’une zone entourant le Button
  • FontFamily est la famille de polices utilisée pour le texte
  • FontSize est la taille du texte
  • FontAttributes indique si le texte est en italique ou en gras
  • BorderWidth est la largeur de la bordure
  • CornerRadius est le rayon d’angle du Button
  • CharacterSpacing est l’espacement entre les caractères du Button texte.
  • TextTransform détermine la casse du Button texte.

Notes

La Button classe a Margin également des propriétés et Padding qui contrôlent le comportement de disposition Buttondu . Pour plus d’informations, consultez la page Marge et remplissage.

Les effets de six de ces propriétés (à l’exception FontFamily et FontAttributes) sont illustrés dans la page Apparence du bouton . Une autre propriété, Image, est abordée dans la section Utilisation de bitmaps avec le bouton .

Toutes les vues et les liaisons de données de la page Apparence du bouton sont définies dans le fichier XAML :

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:ButtonDemos"
             x:Class="ButtonDemos.ButtonAppearancePage"
             Title="Button Appearance">
    <StackLayout>
        <Button x:Name="button"
                Text="Button"
                VerticalOptions="CenterAndExpand"
                HorizontalOptions="Center"
                TextColor="{Binding Source={x:Reference textColorPicker},
                                    Path=SelectedItem.Color}"
                BackgroundColor="{Binding Source={x:Reference backgroundColorPicker},
                                          Path=SelectedItem.Color}"
                BorderColor="{Binding Source={x:Reference borderColorPicker},
                                      Path=SelectedItem.Color}" />

        <StackLayout BindingContext="{x:Reference button}"
                     Padding="10">

            <Slider x:Name="fontSizeSlider"
                    Maximum="48"
                    Minimum="1"
                    Value="{Binding FontSize}" />

            <Label Text="{Binding Source={x:Reference fontSizeSlider},
                                  Path=Value,
                                  StringFormat='FontSize = {0:F0}'}"
                   HorizontalTextAlignment="Center" />

            <Slider x:Name="borderWidthSlider"
                    Minimum="-1"
                    Maximum="12"
                    Value="{Binding BorderWidth}" />

            <Label Text="{Binding Source={x:Reference borderWidthSlider},
                                  Path=Value,
                                  StringFormat='BorderWidth = {0:F0}'}"
                   HorizontalTextAlignment="Center" />

            <Slider x:Name="cornerRadiusSlider"
                    Minimum="-1"
                    Maximum="24"
                    Value="{Binding CornerRadius}" />

            <Label Text="{Binding Source={x:Reference cornerRadiusSlider},
                                  Path=Value,
                                  StringFormat='CornerRadius = {0:F0}'}"
                   HorizontalTextAlignment="Center" />

            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto" />
                    <RowDefinition Height="Auto" />
                    <RowDefinition Height="Auto" />
                </Grid.RowDefinitions>

                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="*" />
                    <ColumnDefinition Width="*" />
                </Grid.ColumnDefinitions>

                <Grid.Resources>
                    <Style TargetType="Label">
                        <Setter Property="VerticalOptions" Value="Center" />
                    </Style>
                </Grid.Resources>

                <Label Text="Text Color:"
                       Grid.Row="0" Grid.Column="0" />

                <Picker x:Name="textColorPicker"
                        ItemsSource="{Binding Source={x:Static local:NamedColor.All}}"
                        ItemDisplayBinding="{Binding FriendlyName}"
                        SelectedIndex="0"
                        Grid.Row="0" Grid.Column="1" />

                <Label Text="Background Color:"
                       Grid.Row="1" Grid.Column="0" />

                <Picker x:Name="backgroundColorPicker"
                        ItemsSource="{Binding Source={x:Static local:NamedColor.All}}"
                        ItemDisplayBinding="{Binding FriendlyName}"
                        SelectedIndex="0"
                        Grid.Row="1" Grid.Column="1" />

                <Label Text="Border Color:"
                       Grid.Row="2" Grid.Column="0" />

                <Picker x:Name="borderColorPicker"
                        ItemsSource="{Binding Source={x:Static local:NamedColor.All}}"
                        ItemDisplayBinding="{Binding FriendlyName}"
                        SelectedIndex="0"
                        Grid.Row="2" Grid.Column="1" />
            </Grid>
        </StackLayout>
    </StackLayout>
</ContentPage>

Le Button en haut de la page a ses trois Color propriétés liées aux Picker éléments en bas de la page. Les éléments des éléments sont des Picker couleurs de la NamedColor classe incluse dans le projet. Trois Slider éléments contiennent des liaisons bidirectionnelle aux FontSizepropriétés , BorderWidthet CornerRadius de .Button

Ce programme vous permet d’expérimenter des combinaisons de toutes ces propriétés :

Apparence du bouton Apparence

Pour voir la Button bordure, vous devez définir un BorderColor sur autre chose que Default, et le sur BorderWidth une valeur positive.

Sur iOS, vous remarquerez que les larges largeurs de bordure s’immiscent à l’intérieur du Button et interfèrent avec l’affichage du texte. Si vous choisissez d’utiliser une bordure avec un iOS Button, vous voudrez probablement commencer et terminer la Text propriété avec des espaces pour conserver sa visibilité.

Sur UWP, la sélection d’un CornerRadius qui dépasse la moitié de la hauteur de déclenche Button une exception.

États visuels du bouton

Button a un PressedVisualState qui peut être utilisé pour lancer une modification Button visuelle du en cas d’appui de l’utilisateur, à condition qu’il soit activé.

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

<Button Text="Click me!"
        ...>
    <VisualStateManager.VisualStateGroups>
        <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>

        </VisualStateGroup>
    </VisualStateManager.VisualStateGroups>
</Button>

spécifie PressedVisualState que lorsque la Button touche est enfoncée, sa Scale propriété passe de sa valeur par défaut de 1 à 0,8. spécifie NormalVisualState que lorsque le Button est dans un état normal, sa Scale propriété est définie sur 1. Par conséquent, l’effet global est que lorsque le Button est enfoncé, il est redimensionné pour être légèrement plus petit, et lorsque le Button est libéré, il est redimensionné à sa taille par défaut.

Pour plus d’informations sur les états visuels, consultez Visual Xamarin.Forms State Manager.

Création d’un bouton bascule

Il est possible de sous-classer Button pour qu’elle fonctionne comme un commutateur marche-arrêt : appuyez une fois sur le bouton pour activer le bouton et appuyez à nouveau dessus pour le désactiver.

La classe suivante ToggleButton dérive de Button et définit un nouvel événement nommé Toggled et une propriété booléenne nommée IsToggled. Il s’agit des deux mêmes propriétés définies par :Xamarin.FormsSwitch

class ToggleButton : Button
{
    public event EventHandler<ToggledEventArgs> Toggled;

    public static BindableProperty IsToggledProperty =
        BindableProperty.Create("IsToggled", typeof(bool), typeof(ToggleButton), false,
                                propertyChanged: OnIsToggledChanged);

    public ToggleButton()
    {
        Clicked += (sender, args) => IsToggled ^= true;
    }

    public bool IsToggled
    {
        set { SetValue(IsToggledProperty, value); }
        get { return (bool)GetValue(IsToggledProperty); }
    }

    protected override void OnParentSet()
    {
        base.OnParentSet();
        VisualStateManager.GoToState(this, "ToggledOff");
    }

    static void OnIsToggledChanged(BindableObject bindable, object oldValue, object newValue)
    {
        ToggleButton toggleButton = (ToggleButton)bindable;
        bool isToggled = (bool)newValue;

        // Fire event
        toggleButton.Toggled?.Invoke(toggleButton, new ToggledEventArgs(isToggled));

        // Set the visual state
        VisualStateManager.GoToState(toggleButton, isToggled ? "ToggledOn" : "ToggledOff");
    }
}

Le ToggleButton constructeur attache un gestionnaire à l’événement Clicked afin qu’il puisse modifier la valeur de la IsToggled propriété. La OnIsToggledChanged méthode déclenche l’événement Toggled .

La dernière ligne de la OnIsToggledChanged méthode appelle la méthode statique VisualStateManager.GoToState avec les deux chaînes de texte « ToggledOn » et « ToggledOff ». Vous pouvez en savoir plus sur cette méthode et sur la façon dont votre application peut répondre aux états visuels dans l’article Le Xamarin.Forms Gestionnaire d’état visuel.

Étant donné que ToggleButton effectue l’appel à VisualStateManager.GoToState, la classe elle-même n’a pas besoin d’inclure d’autres fonctionnalités pour modifier l’apparence du bouton en fonction de son IsToggled état. Il s’agit de la responsabilité du CODE XAML qui héberge le ToggleButton.

La page Désactiver la démonstration du bouton contient deux instances de ToggleButton, y compris le balisage Visual State Manager qui définit le Text, BackgroundColoret TextColor du bouton en fonction de l’état visuel :

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:ButtonDemos"
             x:Class="ButtonDemos.ToggleButtonDemoPage"
             Title="Toggle Button Demo">

    <ContentPage.Resources>
        <Style TargetType="local:ToggleButton">
            <Setter Property="VerticalOptions" Value="CenterAndExpand" />
            <Setter Property="HorizontalOptions" Value="Center" />
        </Style>
    </ContentPage.Resources>

    <StackLayout Padding="10, 0">
        <local:ToggleButton Toggled="OnItalicButtonToggled">
            <VisualStateManager.VisualStateGroups>
                <VisualStateGroup Name="ToggleStates">
                    <VisualState Name="ToggledOff">
                        <VisualState.Setters>
                            <Setter Property="Text" Value="Italic Off" />
                            <Setter Property="BackgroundColor" Value="#C0C0C0" />
                            <Setter Property="TextColor" Value="Black" />
                        </VisualState.Setters>
                    </VisualState>

                    <VisualState Name="ToggledOn">
                        <VisualState.Setters>
                            <Setter Property="Text" Value=" Italic On " />
                            <Setter Property="BackgroundColor" Value="#404040" />
                            <Setter Property="TextColor" Value="White" />
                        </VisualState.Setters>
                    </VisualState>
                </VisualStateGroup>
            </VisualStateManager.VisualStateGroups>
        </local:ToggleButton>

        <local:ToggleButton Toggled="OnBoldButtonToggled">
            <VisualStateManager.VisualStateGroups>
                <VisualStateGroup Name="ToggleStates">
                    <VisualState Name="ToggledOff">
                        <VisualState.Setters>
                            <Setter Property="Text" Value="Bold Off" />
                            <Setter Property="BackgroundColor" Value="#C0C0C0" />
                            <Setter Property="TextColor" Value="Black" />
                        </VisualState.Setters>
                    </VisualState>

                    <VisualState Name="ToggledOn">
                        <VisualState.Setters>
                            <Setter Property="Text" Value=" Bold On " />
                            <Setter Property="BackgroundColor" Value="#404040" />
                            <Setter Property="TextColor" Value="White" />
                        </VisualState.Setters>
                    </VisualState>
                </VisualStateGroup>
            </VisualStateManager.VisualStateGroups>
        </local:ToggleButton>

        <Label x:Name="label"
               Text="Just a little passage of some sample text that can be formatted in italic or boldface by toggling the two buttons."
               FontSize="Large"
               HorizontalTextAlignment="Center"
               VerticalOptions="CenterAndExpand" />

    </StackLayout>
</ContentPage>

Les Toggled gestionnaires d’événements se trouvent dans le fichier code-behind. Ils sont chargés de définir la FontAttributes propriété du Label en fonction de l’état des boutons :

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

    void OnItalicButtonToggled(object sender, ToggledEventArgs args)
    {
        if (args.Value)
        {
            label.FontAttributes |= FontAttributes.Italic;
        }
        else
        {
            label.FontAttributes &= ~FontAttributes.Italic;
        }
    }

    void OnBoldButtonToggled(object sender, ToggledEventArgs args)
    {
        if (args.Value)
        {
            label.FontAttributes |= FontAttributes.Bold;
        }
        else
        {
            label.FontAttributes &= ~FontAttributes.Bold;
        }
    }
}

Voici le programme en cours d’exécution sur iOS, Android et UWP :

Bouton bascule Démo

Utilisation de bitmaps avec des boutons

La Button classe définit une ImageSource propriété qui vous permet d’afficher une image bitmap sur , Buttonseule ou en combinaison avec du texte. Vous pouvez également spécifier la façon dont le texte et l’image sont organisés.

La ImageSource propriété est de type ImageSource, ce qui signifie que les bitmaps peuvent être chargées à partir d’un fichier, d’une ressource incorporée, d’un URI ou d’un flux.

Notes

Bien qu’un Button puisse charger un GIF animé, il affiche uniquement la première image du GIF.

Chaque plateforme prise en charge par Xamarin.Forms permet de stocker des images dans plusieurs tailles pour différentes résolutions de pixels des différents appareils sur lequel l’application peut s’exécuter. Ces multiples bitmaps sont nommées ou stockées de telle sorte que le système d’exploitation puisse choisir la meilleure correspondance pour la résolution d’affichage vidéo de l’appareil.

Pour une bitmap sur un Button, la meilleure taille est généralement comprise entre 32 et 64 unités indépendantes de l’appareil, selon la taille que vous souhaitez. Les images utilisées dans cet exemple sont basées sur une taille de 48 unités indépendantes de l’appareil.

Dans le projet iOS, le dossier Resources contient trois tailles de cette image :

  • Bitmap carrée de 48 pixels stockée en tant que /Resources/MonkeyFace.png
  • Bitmap carrée de 96 pixels stockée en tant que /Resource/MonkeyFace@2x.png
  • Bitmap carrée de 144 pixels stockée en tant que /Resource/MonkeyFace@3x.png

Les trois bitmaps ont reçu une action de génération de BundleResource.

Pour le projet Android, les bitmaps ont tous le même nom, mais ils sont stockés dans des sous-dossiers différents du dossier Resources :

  • Bitmap carrée de 72 pixels stockée sous la forme /Resources/drawable-hdpi/MonkeyFace.png
  • Bitmap carrée de 96 pixels stockée sous la forme /Resources/drawable-xhdpi/MonkeyFace.png
  • Bitmap carrée de 144 pixels stockée sous la forme /Resources/drawable-xxhdpi/MonkeyFace.png
  • Bitmap carrée de 192 pixels stockée sous la forme /Resources/drawable-xxxhdpi/MonkeyFace.png

Ils ont reçu une action de génération d’AndroidResource.

Dans le projet UWP, les bitmaps peuvent être stockées n’importe où dans le projet, mais elles sont généralement stockées dans un dossier personnalisé ou dans le dossier Assets existant. Le projet UWP contient les bitmaps suivantes :

  • Bitmap carrée de 48 pixels stockée en tant que /Assets/MonkeyFace.scale-100.png
  • Bitmap carrée de 96 pixels stockée sous la forme /Assets/MonkeyFace.scale-200.png
  • Bitmap carrée de 192 pixels stockée sous la forme /Assets/MonkeyFace.scale-400.png

Ils ont tous reçu une action de génération de contenu.

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

  • Membre de l’énumération ImagePosition : Left, Top, Rightou Bottom indiquant comment la bitmap apparaît par rapport au texte.
  • Valeur double pour l’espacement entre l’image bitmap et le texte.

Les valeurs par défaut sont Left et 10 unités. Deux propriétés en lecture seule de ButtonContentLayout nommées Position et Spacing fournissent les valeurs de ces propriétés.

Dans le code, vous pouvez créer un Button et définir la ContentLayout propriété comme suit :

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

En XAML, vous devez spécifier 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="image filename"
        ContentLayout="Right, 20" />

La page De démonstration du bouton Image utilise OnPlatform pour spécifier différents noms de fichiers pour les fichiers bitmap iOS, Android et UWP. Si vous souhaitez utiliser le même nom de fichier pour chaque plateforme et éviter l’utilisation de OnPlatform, vous devez stocker les bitmaps UWP dans le répertoire racine du projet.

Le premier Button de la page De démonstration du bouton Image définit la Image propriété, mais pas la Text propriété :

<Button>
    <Button.ImageSource>
        <OnPlatform x:TypeArguments="ImageSource">
            <On Platform="iOS, Android" Value="MonkeyFace.png" />
            <On Platform="UWP" Value="Assets/MonkeyFace.png" />
        </OnPlatform>
    </Button.ImageSource>
</Button>

Si les bitmaps UWP sont stockées dans le répertoire racine du projet, ce balisage peut être considérablement simplifié :

<Button ImageSource="MonkeyFace.png" />

Pour éviter beaucoup de balisage répétitoire dans le fichier ImageButtonDemo.xaml , un implicite Style est également défini pour définir la ImageSource propriété. Cela Style s’applique automatiquement à cinq autres Button éléments. Voici le fichier XAML complet :

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="ButtonDemos.ImageButtonDemoPage">

    <FlexLayout Direction="Column"
                JustifyContent="SpaceEvenly"
                AlignItems="Center">

        <FlexLayout.Resources>
            <Style TargetType="Button">
                <Setter Property="ImageSource">
                    <OnPlatform x:TypeArguments="ImageSource">
                        <On Platform="iOS, Android" Value="MonkeyFace.png" />
                        <On Platform="UWP" Value="Assets/MonkeyFace.png" />
                    </OnPlatform>
                </Setter>
            </Style>
        </FlexLayout.Resources>

        <Button>
            <Button.ImageSource>
                <OnPlatform x:TypeArguments="ImageSource">
                    <On Platform="iOS, Android" Value="MonkeyFace.png" />
                    <On Platform="UWP" Value="Assets/MonkeyFace.png" />
                </OnPlatform>
            </Button.ImageSource>
        </Button>

        <Button Text="Default" />

        <Button Text="Left - 10"
                ContentLayout="Left, 10" />

        <Button Text="Top - 10"
                ContentLayout="Top, 10" />

        <Button Text="Right - 20"
                ContentLayout="Right, 20" />

        <Button Text="Bottom - 20"
                ContentLayout="Bottom, 20" />
    </FlexLayout>
</ContentPage>

Les quatre Button derniers éléments utilisent la ContentLayout propriété pour spécifier une position et un espacement du texte et de l’image bitmap :

Démonstration du bouton Image de démonstration Image

Vous avez maintenant vu les différentes façons de gérer Button les événements et de modifier l’apparence Button .