ToggleButton mudando a imagem dependendo do estado

Eu gostaria de usar ToggleButton da seguinte maneira: Existem 5 imagens diferentes e cada uma delas deve ser exibida dependendo do estado atual:

  1. botão desativado
  2. botão ativado, não verificado
  3. botão habilitado, desmarcado, apontado pelo cursor do mouse
  4. botão ativado, marcado
  5. botão ativado, verificado, apontado pelo cursor do mouse

Eu encontrei um exemplo simples com duas imagens aqui , mas como mudar a imagem dependendo da propriedade “checked”?

A segunda pergunta: como posso evitar criar estilos diferentes para cada botão em meu aplicativo? Eu estou usando cerca de 20 botões diferentes e cada um deles tem um conjunto diferente de icons.

Até agora estou usando apenas um ícone, abaixo do meu código. É possível ter código comum (estilo e modelo) e definir a fonte de imagens na seção onde eu quero criar o botão (como na seção 3 do meu código)?

                             

Você pode obter a funcionalidade que deseja criando um UserControl que expõe propriedades de dependência para Command, IsChecked e uma para cada imagem com estado. Seu controle de usuário irá conter um botão de alternância e imagem.

Você pode usar MultiDataTriggers para detectar seu estado e trocar a imagem dependendo do estado.

Como você expôs as DependencyProperties para as imagens com estado, elas podem ser definidas usando Ligação de Dados sempre que você declarar seu controle. Os gatilhos mudam automaticamente a fonte da imagem para você, uma vez que o estado muda.

[Edit: Adicionado algum código para ajudar a explicar]

Aqui está um exemplo parcial para você começar:

MyToggleButton.xaml:

          

E o arquivo cs:

 using System; using System.Windows; using System.Windows.Controls; using System.Windows.Media; namespace ToggleTest { ///  /// Interaction logic for ToggleButton.xaml ///  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 } } } 

Esse controle pode ser usado assim:

  

Esta solução é simples:

          

Sir Ed Gonzalez, obrigado por bom exemplo.

O único problema é que a binding à propriedade de dependência MyToggleButton.IsChecked não funciona corretamente (plataforma: Windows 7., NET 4.0, VS2010). Então, fiz algumas alterações no seu exemplo.

xaml:

    

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

O padrão de uso permanece sem restrições:

  

Eu fiz o mesmo para o meu RibbonToggleButton, mas um pouco mais fácil eu acho. Eu coloquei o gatilho de estilo dentro do botão em vez de usar um elemento de imagem extra.

        

Sir Ed Gonzalez, obrigado por bom exemplo.

O único problema é que a binding à propriedade de dependência MyToggleButton.IsChecked não funciona corretamente (plataforma: Windows 7., NET 4.0, VS2010). Então, fiz algumas alterações no seu exemplo.

Apenas remova a static em IsChecked DependencyProperty, adicione seu ChangeImage() em IsChecked() e o exemplo de Sir Ed Gonzalez funciona bem ^^

 public readonly DependencyProperty IsCheckedProperty = DependencyProperty.Register( "IsChecked" ... public Boolean IsChecked ... if (value != IsChecked) SetValue(IsCheckedProperty, value); ChangeImage();