web-dev-qa-db-fra.com

ToggleButton changer d'image en fonction de l'état

J'aimerais utiliser ToggleButton de la manière suivante: Il y a 5 images différentes et chacune d’elles devrait être affichée en fonction de l’état actuel:

  1. bouton désactivé
  2. bouton activé, décoché
  3. bouton activé, décoché, pointé par le curseur de la souris
  4. bouton activé, vérifié
  5. bouton activé, coché, pointé par le curseur de la souris

J'ai trouvé un exemple simple avec deux images ici , mais comment changer l'image en fonction de la propriété "cochée"?

La deuxième question: comment puis-je éviter de créer des styles différents pour chaque bouton de mon application? J'utilise environ 20 boutons différents et chacun d'entre eux a un ensemble différent d'icônes.

Jusqu'à présent, je n'utilise qu'une seule icône, en dessous de mon code. Est-il possible d'avoir un code commun (style et modèle) et de définir la source des images dans la section où je veux créer un bouton (comme dans la section 3 de mon code)?

<ControlTemplate x:Key="ToggleButtonTemplate" TargetType="{x:Type ToggleButton}">
    <Grid>
        <Border x:Name="ContentBorder" CornerRadius="4" BorderBrush="Transparent" BorderThickness="1" Background="{DynamicResource ButtonOff}">
            <ContentPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" RecognizesAccessKey="True"/>
        </Border>
    </Grid>
    <ControlTemplate.Triggers>
        <Trigger Property="IsPressed" Value="true">
            <Setter TargetName="ContentBorder" Property="Background" Value="{DynamicResource ButtonOn}"/>
        </Trigger>
        <Trigger Property="IsChecked" Value="true">
            <Setter TargetName="ContentBorder" Property="Background" Value="{DynamicResource ButtonOn}"/>
        </Trigger>
        <Trigger Property="IsEnabled" Value="false">
            <Setter TargetName="ContentBorder" Property="Background" Value="{DynamicResource ButtonDisabled}"/>
            <Setter Property="Foreground" Value="{DynamicResource BorderDisabled}"/>
        </Trigger>
    </ControlTemplate.Triggers>
</ControlTemplate>

<Style x:Key="ToggleButtonStyle" TargetType="{x:Type ToggleButton}">
    <Setter Property="Width" Value="64" />
    <Setter Property="Height" Value="64" />
    <Setter Property="HorizontalContentAlignment" Value="Center"/>
    <Setter Property="VerticalContentAlignment" Value="Center"/>
    <Setter Property="Template" Value="{DynamicResource ToggleButtonTemplate}" />
</Style>

<ToggleButton IsChecked="{Binding Path=IsLectorModeEnabled}" Command="{Binding CmdLector}" Style="{DynamicResource ToggleButtonStyle}">
    <Image Source="{DynamicResource LectorImage}" HorizontalAlignment="Center" VerticalAlignment="Center" Stretch="None" />
</ToggleButton>
13
mack369

Vous pouvez obtenir la fonctionnalité souhaitée en créant un UserControl qui expose les propriétés de dépendance pour Command, IsChecked et un pour chaque image avec état. Votre contrôle utilisateur contiendra un bouton bascule et une image.

Vous pouvez utiliser MultiDataTriggers pour détecter votre état et sélectionner l'image en fonction de l'état.

Comme vous avez exposé les propriétés DependencyProperties pour les images avec état, elles peuvent être définies à l'aide de la liaison de données partout où vous déclarez votre contrôle. Les déclencheurs basculeront automatiquement la source de l'image pour vous, une fois que l'état aura changé.

[Edit: Ajout de code pour aider à expliquer]

Voici un exemple partiel pour vous aider à démarrer:

MyToggleButton.xaml:

<UserControl x:Class="ToggleTest.MyToggleButton"
xmlns="http://schemas.Microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.Microsoft.com/winfx/2006/xaml">
<ToggleButton
    IsChecked='{Binding RelativeSource={RelativeSource FindAncestor, 
    AncestorType={x:Type ToggleButton} }, 
    Path=IsChecked}'>
    <Image
        x:Name='ButtonImage'>
        <Image.Style>
            <Style
                TargetType='{x:Type Image}'>
                <Style.Triggers>
                    <MultiDataTrigger>
                        <MultiDataTrigger.Conditions>
                            <Condition
                                Binding='{Binding 
                                RelativeSource={RelativeSource FindAncestor, 
                                AncestorType={x:Type ToggleButton} }, 
                                Path=IsChecked}'
                                Value='True' />
                            <Condition
                                Binding='{Binding 
                                RelativeSource={RelativeSource Self}, 
                                Path=IsEnabled}'
                                Value='True' />
                        </MultiDataTrigger.Conditions>
                        <Setter
                            Property='Source'
                            Value='{Binding 
                            RelativeSource={RelativeSource FindAncestor, 
                            AncestorType={x:Type UserControl} }, 
                            Path=EnabledChecked}' />
                    </MultiDataTrigger>
                    <MultiDataTrigger>
                        <MultiDataTrigger.Conditions>
                            <Condition
                                Binding='{Binding 
                                RelativeSource={RelativeSource FindAncestor, 
                                AncestorType={x:Type ToggleButton} }, 
                                Path=IsChecked}'
                                Value='False' />
                            <Condition
                                Binding='{Binding 
                                RelativeSource={RelativeSource Self}, 
                                Path=IsEnabled}'
                                Value='True' />
                        </MultiDataTrigger.Conditions>
                        <Setter
                            Property='Source'
                            Value='{Binding 
                            RelativeSource={RelativeSource FindAncestor, 
                            AncestorType={x:Type UserControl} }, 
                            Path=EnabledUnchecked}' />
                    </MultiDataTrigger>
                    <MultiDataTrigger>
                        <MultiDataTrigger.Conditions>
                            <Condition
                                Binding='{Binding 
                                RelativeSource={RelativeSource FindAncestor, 
                                AncestorType={x:Type ToggleButton} }, 
                                Path=IsChecked}'
                                Value='False' />
                            <Condition
                                Binding='{Binding 
                                RelativeSource={RelativeSource Self}, 
                                Path=IsEnabled}'
                                Value='False' />
                        </MultiDataTrigger.Conditions>
                        <Setter
                            Property='Source'
                            Value='{Binding 
                            RelativeSource={RelativeSource FindAncestor, 
                            AncestorType={x:Type UserControl} }, 
                            Path=DisabledUnchecked}' />
                    </MultiDataTrigger>
                </Style.Triggers>
            </Style>
        </Image.Style>
    </Image>
</ToggleButton>

Et le fichier cs:

using System;

    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Media;

    namespace ToggleTest

{
    /// <summary>
    /// Interaction logic for ToggleButton.xaml
    /// </summary>
    public partial class MyToggleButton : UserControl
    {
        public MyToggleButton()
        {
            InitializeComponent();
        }


        public static readonly DependencyProperty EnabledUncheckedProperty =
            DependencyProperty.Register(
            "EnabledUnchecked",
            typeof(ImageSource),
            typeof(MyToggleButton),
            new PropertyMetadata(onEnabledUncheckedChangedCallback));

        public ImageSource EnabledUnchecked
        {
            get { return (ImageSource)GetValue(EnabledUncheckedProperty); }
            set { SetValue(EnabledUncheckedProperty, value); }
        }

        static void onEnabledUncheckedChangedCallback(
            DependencyObject dobj,
            DependencyPropertyChangedEventArgs args)
        {
            //do something if needed
        }

        public static readonly DependencyProperty DisabledUncheckedProperty =
            DependencyProperty.Register(
            "DisabledUnchecked",
            typeof(ImageSource),
            typeof(MyToggleButton),
            new PropertyMetadata(onDisabledUncheckedChangedCallback));

        public ImageSource DisabledUnchecked
        {
            get { return (ImageSource)GetValue(DisabledUncheckedProperty); }
            set { SetValue(DisabledUncheckedProperty, value); }
        }

        static void onDisabledUncheckedChangedCallback(
            DependencyObject dobj,
            DependencyPropertyChangedEventArgs args)
        {
            //do something if needed
        }


        public static readonly DependencyProperty EnabledCheckedProperty =
            DependencyProperty.Register(
            "EnabledChecked",
            typeof(ImageSource),
            typeof(MyToggleButton),
            new PropertyMetadata(onEnabledCheckedChangedCallback));

        public ImageSource EnabledChecked
        {
            get { return (ImageSource)GetValue(EnabledCheckedProperty); }
            set { SetValue(EnabledCheckedProperty, value); }
        }

        static void onEnabledCheckedChangedCallback(
            DependencyObject dobj,
            DependencyPropertyChangedEventArgs args)
        {
            //do something if needed
        }


        public static readonly DependencyProperty IsCheckedProperty =
            DependencyProperty.Register(
            "IsChecked",
            typeof(Boolean),
            typeof(MyToggleButton),
            new PropertyMetadata(onCheckedChangedCallback));

        public Boolean IsChecked
        {
            get { return (Boolean)GetValue(IsCheckedProperty); }
            set { if(value != IsChecked) SetValue(IsCheckedProperty, value); }
        }

        static void onCheckedChangedCallback(
            DependencyObject dobj,
            DependencyPropertyChangedEventArgs args)
        {
            //do something, if needed
        }



    }
}

Ce contrôle pourrait être utilisé comme suit:

<local:MyToggleButton
            IsChecked='True'
            IsEnabled='False'
            EnabledChecked='<add your image source here>'
            EnabledUnchecked='<add your image source here>'
            DisabledUnchecked='<add your image source here>'/>
11
Ed Gonzalez

Cette solution est simple:

 <ToggleButton IsChecked="{Binding IsCheckedState}">
            <Image Width="24" Height="24"  >
                <Image.Style>
                    <Style TargetType="{x:Type Image}">
                        <Style.Triggers>
                            <DataTrigger Binding="{Binding IsCheckedState}" Value="true">
                                <Setter Property="Source" Value="Images/checked.ico"/>
                            </DataTrigger>
                            <DataTrigger Binding="{Binding IsCheckedState}" Value="false">
                                <Setter Property="Source" Value="Images/unchecked.ico"/>
                            </DataTrigger>
                        </Style.Triggers>
                    </Style>
                </Image.Style>
            </Image>
        </ToggleButton>
35
Doron Neumann

Sir Ed Gonzalez, merci pour votre bon exemple.

Le seul problème est que la liaison à la propriété de dépendance MyToggleButton.IsChecked ne fonctionne pas correctement (plate-forme: Windows 7., NET 4.0, VS2010). J'ai donc apporté quelques modifications à votre exemple.

xaml:

<ToggleButton x:Class="MyApp.ToggleButtonEx"
         xmlns="http://schemas.Microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.Microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         Checked="ToggleButton_CheckedChanged"
         Unchecked="ToggleButton_CheckedChanged"
         IsEnabledChanged="ToggleButton_IsEnabledChanged"
         Loaded="ToggleButton_Loaded">
    <Image x:Name='ButtonImage'/>
</ToggleButton>

cs:

public partial class ToggleButtonEx : ToggleButton
{
    public ToggleButtonEx()
    {
        InitializeComponent();            
    }

    public static readonly DependencyProperty EnabledUncheckedProperty =
        DependencyProperty.Register(
        "EnabledUnchecked",
        typeof(ImageSource),
        typeof(ToggleButtonEx),
        new PropertyMetadata(onEnabledUncheckedChangedCallback));

    public ImageSource EnabledUnchecked
    {
        get { return (ImageSource)GetValue(EnabledUncheckedProperty); }
        set { SetValue(EnabledUncheckedProperty, value); }
    }

    static void onEnabledUncheckedChangedCallback(
        DependencyObject dobj,
        DependencyPropertyChangedEventArgs args)
    {
        //do something if needed
    }

    public static readonly DependencyProperty DisabledUncheckedProperty =
        DependencyProperty.Register(
        "DisabledUnchecked",
        typeof(ImageSource),
        typeof(ToggleButtonEx),
        new PropertyMetadata(onDisabledUncheckedChangedCallback));

    public ImageSource DisabledUnchecked
    {
        get { return (ImageSource)GetValue(DisabledUncheckedProperty); }
        set { SetValue(DisabledUncheckedProperty, value); }
    }

    static void onDisabledUncheckedChangedCallback(
        DependencyObject dobj,
        DependencyPropertyChangedEventArgs args)
    {
        //do something if needed
    }


    public static readonly DependencyProperty EnabledCheckedProperty =
        DependencyProperty.Register(
        "EnabledChecked",
        typeof(ImageSource),
        typeof(ToggleButtonEx),
        new PropertyMetadata(onEnabledCheckedChangedCallback));

    public ImageSource EnabledChecked
    {
        get { return (ImageSource)GetValue(EnabledCheckedProperty); }
        set { SetValue(EnabledCheckedProperty, value); }
    }

    static void onEnabledCheckedChangedCallback(
        DependencyObject dobj,
        DependencyPropertyChangedEventArgs args)
    {
        //do something if needed
    }

    private void ToggleButton_CheckedChanged(object sender, RoutedEventArgs e)
    {
        ChangeImage();
    }

    private void ToggleButton_IsEnabledChanged(object sender, DependencyPropertyChangedEventArgs e)
    {
        ChangeImage();
    }

    private void ToggleButton_Loaded(object sender, RoutedEventArgs e)
    {
        ChangeImage();
    }

    private void ChangeImage()
    {
        if (IsEnabled)
        {
            if(IsChecked == true)
                ButtonImage.Source = EnabledChecked;
            else
                ButtonImage.Source = EnabledUnchecked;
        }
        else
        {
            ButtonImage.Source = DisabledUnchecked;
        }
    }
}

Le modèle d'utilisation reste inchangé:

<local:MyToggleButton
        IsChecked='True'
        IsEnabled='False'
        EnabledChecked='<add your image source here>'
        EnabledUnchecked='<add your image source here>'
        DisabledUnchecked='<add your image source here>'/>
5
JSP

J'ai fait la même chose pour mon RibbonToggleButton, mais un peu plus facile je pense. Je mets le déclencheur de style à l'intérieur du bouton au lieu d'utiliser un élément d'image supplémentaire.

 <RibbonToggleButton Label="{x:Static p:Resources.Main_Connect}" Command="{Binding ConnectRemoteCommand}" CommandParameter="{Binding Path=IsChecked, RelativeSource={RelativeSource Self}}">
                        <RibbonToggleButton.Style>
                            <Style TargetType="{x:Type RibbonToggleButton}">
                                <Style.Triggers>
                                    <DataTrigger Binding="{Binding Path=IsChecked, RelativeSource={RelativeSource Self}}" Value="true">
                                        <Setter Property="LargeImageSource" Value="../../Resources/Images/GPS-On.png"/>
                                    </DataTrigger>
                                    <DataTrigger Binding="{Binding Path=IsChecked, RelativeSource={RelativeSource Self}}" Value="false">
                                        <Setter Property="LargeImageSource" Value="../../Resources/Images/GPS-Off.png"/>
                                    </DataTrigger>
                                </Style.Triggers>
                            </Style>
                        </RibbonToggleButton.Style>
                    </RibbonToggleButton>
1
kevingoos