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:
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>
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>'/>
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>
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>'/>
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>