2010-03-18 7 views
12

Je voudrais utiliser ToggleButton de manière suivante: Il y a 5 images différentes et chacune d'entre elles doivent être affichées en fonction de l'état actuel:changement d'image ToggleButton selon l'état

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

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

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'eux a un ensemble d'icônes différent.

Jusqu'à présent, j'utilise 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 d'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> 

Répondre

9

Vous pouvez obtenir la fonctionnalité que vous voulez en créant un UserControl qui expose les propriétés de dépendance pour le commandement, IsChecked, et un pour chaque image stateful. Votre contrôle utilisateur contiendra un bouton bascule et une image.

Vous pouvez utiliser MultiDataTriggers pour détecter votre état et échanger l'image en fonction de l'état. Comme vous avez exposé DependencyProperties pour les images avec état, elles peuvent être définies à l'aide de DataBinding chaque fois que vous déclarez votre contrôle. Les déclencheurs changeront automatiquement la source de l'image pour vous, une fois que l'état change.

[Edit: ajout de code pour 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 cs fichier:

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 ceci:

<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

Sir Ed Gonzalez, je vous remercie de 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 fait quelques changements dans 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; 
     } 
    } 
} 

modèle d'utilisation reste unchaged:

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

Cela a très bien fonctionné pour moi (et j'ai appris une chose ou deux!). Bon travail! – Flea

-1

Sir Ed Gonzalez, je vous remercie de 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 fait quelques changements dans votre exemple.

supprimer Juste statique sur IsChecked DependencyProperty, ajoutez votre ChangeImage() dans IsChecked() et l'exemple fonctionne bien ^^

public readonly DependencyProperty IsCheckedProperty = 
      DependencyProperty.Register(
      "IsChecked" ... 

public Boolean IsChecked 
... if (value != IsChecked) SetValue(IsCheckedProperty, value); ChangeImage(); 
+3

Cela ne fonctionnera pas, ces get/set ne sont pas appelés par le framework. –

32

Sir 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> 
+1

Bref éclaircissement, le 'IsCheckedState' ci-dessus est une propriété de la machine virtuelle, qui n'a rien à voir avec WPF. C'est à dire. Si vous avez une propriété VM de 'IsNewUser' à lier, vous devez remplacer 'IsCheckedState' dans l'exemple ci-dessus pour 'IsNewUser'. – HockeyJ

+0

fonctionne comme un charme! –

0

I a fait de même pour mon RibbonToggleButton, mais un peu plus facile je pense. J'ai mis 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>