Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Toggle button command not executed

The problem is this. Let's say I have 3 toggle buttons and I want just one being checked at the time using Command. When one button is checked others should be disabled. (I don't want to use radio buttons). So I created this simple code but the strange thing is, that when checked button is clicked commands Execute is not executed (no MessageBox is shown).

<Window x:Class="ToggleButtonsProblem.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525">
<StackPanel>
    <ToggleButton Command="{Binding ToggleCommand}" CommandParameter="{Binding RelativeSource={RelativeSource Self}}">A</ToggleButton>
    <ToggleButton Command="{Binding ToggleCommand}" CommandParameter="{Binding RelativeSource={RelativeSource Self}}">B</ToggleButton>
    <ToggleButton Command="{Binding ToggleCommand}" CommandParameter="{Binding RelativeSource={RelativeSource Self}}">C</ToggleButton>
</StackPanel>

using System;
using System.Windows;
using System.Windows.Input;
using System.Windows.Controls.Primitives;

namespace ToggleButtonsProblem {
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window {
    public MainWindow() {
        InitializeComponent();
        this.DataContext = new ViewModel();
    }
}

public class ViewModel {
    public static ICommand ToggleCommand { get { return new ToggleCommand(); } }
}

public class ToggleCommand : ICommand {
    public static bool isSomeChecked = false;
    public static ToggleButton currentCheckedButton;

    public bool CanExecute(object parameter) {
        if (currentCheckedButton == null) return true;
        return (parameter as ToggleButton).IsChecked == true;
    }

    public event EventHandler CanExecuteChanged {
        add { CommandManager.RequerySuggested += value; }
        remove { CommandManager.RequerySuggested -= value; }
    }

    public void Execute(object parameter) {
        currentCheckedButton = null;
        ToggleButton button = parameter as ToggleButton;
        MessageBox.Show(button.IsChecked.ToString());
        if (button.IsChecked == true) {
            currentCheckedButton = button;
        }
        else {                
            currentCheckedButton = null;
        }
    }
}

}

like image 948
Martin Avatar asked Jul 31 '26 19:07

Martin


1 Answers

Commands are executed only when button is pressed. You need to hook the Unchecked event of the ToggleButton, for example like this:

<ToggleButton Command="{Binding ToggleCommand}" Unchecked="ToggleButton_Unchecked" CommandParameter="{Binding RelativeSource={RelativeSource Self}}">A</ToggleButton>

And add method handler to the code-behind class:

public void ToggleButton_Unchecked(object sender, RoutedEventArgs e) {
    (sender as ToggleButton).Command.Execute(sender);
}

This should work, perhaps you can find some prettier way of adding the method handler, maybe as a part of ToggleCommand class.

EDIT: Try implementing your CanExecute() method like this:

public bool CanExecute(object parameter) {            
    if (currentCheckedButton == null) return true;
    return currentCheckedButton == parameter;
}

For me it works. Here is what I think caused the problem: you click (uncheck) the button, so IsChecked changed to false. Then WPF attempts to invoke the Execute() method, but as always, calls CanExecute() first. However, CanExecute() returns false, because the check state has already been changed, so the Execute() methods is not invoked.

like image 72
cre8or Avatar answered Aug 03 '26 08:08

cre8or



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!