using System; using System.ComponentModel; using Avalonia.Automation.Peers; using Avalonia.Controls.Metadata; using Avalonia.Data; using Avalonia.Interactivity; namespace Avalonia.Controls.Primitives { /// /// Represents a control that a user can select (check) or clear (uncheck). Base class for controls that can switch states. /// [PseudoClasses(":checked", ":unchecked", ":indeterminate")] public class ToggleButton : Button { /// /// Defines the property. /// public static readonly StyledProperty IsCheckedProperty = AvaloniaProperty.Register(nameof(IsChecked), false, defaultBindingMode: BindingMode.TwoWay); /// /// Defines the property. /// public static readonly StyledProperty IsThreeStateProperty = AvaloniaProperty.Register(nameof(IsThreeState)); /// /// Defines the event. /// public static readonly RoutedEvent IsCheckedChangedEvent = RoutedEvent.Register( nameof(IsCheckedChanged), RoutingStrategies.Bubble); static ToggleButton() { } public ToggleButton() { UpdatePseudoClasses(IsChecked); } /// /// Raised when the property value changes. /// public event EventHandler? IsCheckedChanged { add => AddHandler(IsCheckedChangedEvent, value); remove => RemoveHandler(IsCheckedChangedEvent, value); } /// /// Gets or sets whether the is checked. /// public bool? IsChecked { get => GetValue(IsCheckedProperty); set => SetValue(IsCheckedProperty, value); } /// /// Gets or sets a value that indicates whether the control supports three states. /// public bool IsThreeState { get => GetValue(IsThreeStateProperty); set => SetValue(IsThreeStateProperty, value); } protected override void OnClick() { if (!IsEffectivelyEnabled) { return; } Toggle(); base.OnClick(); } /// /// Toggles the property. /// protected virtual void Toggle() { bool? newValue; if (IsChecked.HasValue) { if (IsChecked.Value) { if (IsThreeState) { newValue = null; } else { newValue = false; } } else { newValue = true; } } else { newValue = false; } SetCurrentValue(IsCheckedProperty, newValue); } /// /// Called when changes. /// /// Event arguments for the routed event that is raised by the default implementation of this method. protected virtual void OnIsCheckedChanged(RoutedEventArgs e) { RaiseEvent(e); } protected override AutomationPeer OnCreateAutomationPeer() { return new ToggleButtonAutomationPeer(this); } /// protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) { base.OnPropertyChanged(change); if (change.Property == IsCheckedProperty) { var newValue = change.GetNewValue(); UpdatePseudoClasses(newValue); OnIsCheckedChanged(new RoutedEventArgs(IsCheckedChangedEvent)); } } private void UpdatePseudoClasses(bool? isChecked) { PseudoClasses.Set(":checked", isChecked == true); PseudoClasses.Set(":unchecked", isChecked == false); PseudoClasses.Set(":indeterminate", isChecked == null); } } }