Xamarin.Forms Bouton

Le bouton répond à un appui ou un clic qui dirige une application pour effectuer une tâche particulière.

Il Button s’agit du contrôle interactif le plus fondamental dans tous les Xamarin.Forms. Le Button texte 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. L’utilisateur appuie sur le Button doigt ou clique dessus avec une souris pour lancer cette commande.

Gestion des clics sur le bouton

Button définit un Clicked événement déclenché lorsque l’utilisateur appuie sur l’utilisateur Button avec 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. La Button propriété doit IsEnabled être définie true pour qu’elle réponde aux appuis.

La page Clic de bouton de base de l’exemple montre comment instancier un Button élément XAML et gérer son Clicked événement. Le fichier BasicButtonClickPage.xaml contient à la fois un Label StackLayout 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>

Les Button tendances occupent tout l’espace qui lui est permis. Par exemple, si vous ne définissez pas la HorizontalOptions propriété d’une Button autre valeur que Fill, la Button largeur totale de son parent est occupée.

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

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 objets Button qui partagent le même événement Clicked.

Ce gestionnaire particulier Clicked appelle une fonction d’animation qui fait pivoter les Label 360 degrés en 1000 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 :

Clic sur le bouton De base

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

Chaque plateforme restitue de Button 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 FontFamily, FontSizeet FontAttributes les propriétés.

Création d’un bouton dans le code

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

La page Clic du bouton de code montre comment créer une page qui est fonctionnellement équivalente à la page Clic de 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 fait dans le constructeur de la classe. Étant donné que le Clicked gestionnaire n’est 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 (comme la OnButtonClick méthode dans Basic Button Click) et attacher cette méthode à l’événement :

button.Clicked += OnButtonClicked;

Désactivation du bouton

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

Utilisation de l’interface de commande

Il est possible qu’une application réponde aux Button appuis 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 en lien avec la liaison de données, et en particulier lors de l’implémentation de l’architecture Model-View-ViewModel (MVVM). Ces rubriques sont abordées dans les articles De liaison de données, De liaisons de données à MVVM et MVVM.

Dans une application MVVM, le viewmodel définit les 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 et Command<T> classes qui implémentent l’interface ICommand et aident le viewmodel à définir les propriétés du 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 montre l’approche de base.

La CommandDemoViewModel classe est un viewmodel très simple qui définit une propriété de type double nommé 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 la moitié de la Number propriété.

Le fichier BasicButtonCommand.xaml définit sa BindingContext valeur sur une instance de CommandDemoViewModel. L’élément Label et 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>

À mesure que les deux Button éléments sont appuyés, les commandes sont exécutées et le nombre change de valeur :

Commande de bouton de base

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 Command objets contrôlent l’activation et la désactivation des Button éléments. 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é canExecute argument) qui retourne true si la Button valeur doit être activée. Voici la modification du 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 sont Command nécessaires pour que la Command méthode puisse appeler la canExecute méthode et déterminer si la Button méthode doit être désactivée ou non. Avec ce changement de code, à mesure que le nombre atteint la limite, il Button est désactivé :

Commande de bouton de base - Modifié

Il est possible que deux éléments ou plus Button soient liés à la même ICommand propriété. 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. Cette technique est présentée en détail dans la section Commandes de base de l’article Interface de commande.

L’exemple utilise également cette technique dans sa MainPage classe. Le fichier MainPage.xaml contient une 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 elle CommandParameter est définie sur un Type objet correspondant à l’une 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 il s’agit du 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 se termine par la définition de sa BindingContext valeur elle-même. Cela est nécessaire pour que les propriétés du fichier XAML se lient à la NavigateCommand propriété.

Appuyez et relâchez 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 Buttonbouton , ou qu’un bouton de la souris est enfoncé avec le pointeur positionné sur le Button. L’événement Released se produit lorsque le doigt ou le bouton de la souris est libéré. 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 de l’événement Button avant d’être libéré, l’événement Clicked peut ne pas se produire.

Les Pressed événements et Released les événements 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 attachés pour les événements et Released les Pressed événements :

<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 événement Pressed se produit, mais suspend la rotation lorsqu’un événement Released 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é :

Bouton Appuyer et libérer

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

Apparence du bouton

Il Button hérite 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 pour 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 italique ou 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.

Remarque

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

Les effets de six de ces propriétés (à l’exclusion FontFamily et FontAttributes) sont illustrés dans la page Apparence du bouton. Une autre propriété, Imageest décrite dans la section Utilisation de bitmaps avec bouton.

Toutes les vues et liaisons de données dans 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>

En Button haut de la page, ses trois Color propriétés sont liées aux Picker éléments en bas de la page. Les éléments des éléments des Picker éléments sont des couleurs de la NamedColor classe incluse dans le projet. Trois Slider éléments contiennent des liaisons bidirectionnelle pour les propriétés et les CornerRadius FontSizeBorderWidthpropriétés du .Button

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

Apparence du bouton

Pour voir la Button bordure, vous devez définir une BorderColor valeur autre que Defaultcelle de la bordure et la BorderWidth valeur positive.

Sur iOS, vous remarquerez que de grandes largeurs de bordure intrusent dans l’intérieur du Button texte et interfèrent avec l’affichage du texte. Si vous choisissez d’utiliser une bordure avec un iOS Button, vous souhaiterez probablement commencer et mettre fin à 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 l’exception Button déclenche une exception.

États visuels de Button

Button a un Pressed VisualState élément qui peut être utilisé pour initier une modification Button visuelle au moment où il est appuyé par l’utilisateur, à condition qu’il soit activé.

L’exemple de 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>

Indique Pressed VisualState que lorsque l’utilisateur Button appuie, sa Scale propriété est remplacée par sa valeur par défaut de 1 à 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.

Pour plus d’informations sur les états visuels, consultez Le Xamarin.Forms Gestionnaire d’état visuel.

Création d’un bouton bascule

Il est possible de sous-classe Button afin qu’elle fonctionne comme un commutateur activé : appuyez une fois sur le bouton pour activer le bouton et appuyez de nouveau dessus pour le désactiver.

La classe suivante ToggleButton dérive 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 les Xamarin.FormsSwitchéléments suivants :

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 fait l’appel à VisualStateManager.GoToState, la classe elle-même n’a pas besoin d’inclure d’autres installations pour modifier l’apparence du bouton en fonction de son IsToggled état. C’est la responsabilité du xaml qui héberge le ToggleButton.

La page De démonstration de bouton bascule 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 responsables de la définition de la FontAttributes propriété de l’état Label 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 :

Activer/désactiver la démonstration du bouton

Utilisation de bitmaps avec des boutons

La Button classe définit une propriété qui vous permet d’afficher ImageSource une 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.

Remarque

Alors qu’une Button image GIF animée peut charger une image GIF animée, elle affiche uniquement le premier cadre du GIF.

Chaque plateforme prise en charge permet Xamarin.Forms aux images d’être stockées dans plusieurs tailles pour différentes résolutions de pixels des différents appareils sur utilisant l’application. Ces plusieurs 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 souhaitée. 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 Ressources contient trois tailles de cette image :

  • Bitmap carrée de 48 pixels stockée en tant que /Resources/MonkeyFace.png
  • Image bitmap carrée de 96 pixels stockée en tant que /Resource/MonkeyFace@2x.png
  • Image 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 elles sont stockées dans différents sous-dossiers du dossier Ressources :

  • Bitmap carrée de 72 pixels stockée en tant que /Resources/drawable-hdpi/MonkeyFace.png
  • Bitmap carrée de 96 pixels stockée en tant que /Resources/drawable-xhdpi/MonkeyFace.png
  • Image bitmap carrée de 144 pixels stockée en tant que /Resources/drawable-xxhdpi/MonkeyFace.png
  • Image bitmap carrée de 192 pixels stockée en tant que /Resources/drawable-xxxhdpi/MonkeyFace.png

Celles-ci 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 ces bitmaps :

  • Bitmap carrée de 48 pixels stockée en tant que /Assets/MonkeyFace.scale-100.png
  • Bitmap carrée de 96 pixels stockée en tant que /Assets/MonkeyFace.scale-200.png
  • Bitmap carrée de 192 pixels stockée en tant que /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 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, qui est une classe incorporée dans Button. Le 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.

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

Dans le code, vous pouvez créer et Button 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 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.

La première Button 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 un grand nombre de marques répétitives dans le fichier ImageButtonDemo.xaml , un implicite Style est également défini pour définir la ImageSource propriété. Cette opération Style est automatiquement appliquée à 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 la bitmap :

Démonstration du bouton Image

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