77
88namespace Avalonia . Controls . Primitives
99{
10+ /// <summary>
11+ /// Represents a control that a user can select (check) or clear (uncheck). Base class for controls that can switch states.
12+ /// </summary>
1013 public class ToggleButton : Button
1114 {
15+ /// <summary>
16+ /// Defines the <see cref="IsChecked"/> property.
17+ /// </summary>
1218 public static readonly DirectProperty < ToggleButton , bool ? > IsCheckedProperty =
1319 AvaloniaProperty . RegisterDirect < ToggleButton , bool ? > (
1420 nameof ( IsChecked ) ,
@@ -17,24 +23,80 @@ public class ToggleButton : Button
1723 unsetValue : null ,
1824 defaultBindingMode : BindingMode . TwoWay ) ;
1925
26+ /// <summary>
27+ /// Defines the <see cref="IsThreeState"/> property.
28+ /// </summary>
2029 public static readonly StyledProperty < bool > IsThreeStateProperty =
2130 AvaloniaProperty . Register < ToggleButton , bool > ( nameof ( IsThreeState ) ) ;
2231
32+ /// <summary>
33+ /// Defines the <see cref="Checked"/> event.
34+ /// </summary>
35+ public static readonly RoutedEvent < RoutedEventArgs > CheckedEvent =
36+ RoutedEvent . Register < ToggleButton , RoutedEventArgs > ( nameof ( Checked ) , RoutingStrategies . Bubble ) ;
37+
38+ /// <summary>
39+ /// Defines the <see cref="Unchecked"/> event.
40+ /// </summary>
41+ public static readonly RoutedEvent < RoutedEventArgs > UncheckedEvent =
42+ RoutedEvent . Register < ToggleButton , RoutedEventArgs > ( nameof ( Unchecked ) , RoutingStrategies . Bubble ) ;
43+
44+ /// <summary>
45+ /// Defines the <see cref="Unchecked"/> event.
46+ /// </summary>
47+ public static readonly RoutedEvent < RoutedEventArgs > IndeterminateEvent =
48+ RoutedEvent . Register < ToggleButton , RoutedEventArgs > ( nameof ( Indeterminate ) , RoutingStrategies . Bubble ) ;
49+
2350 private bool ? _isChecked = false ;
2451
2552 static ToggleButton ( )
2653 {
2754 PseudoClass < ToggleButton , bool ? > ( IsCheckedProperty , c => c == true , ":checked" ) ;
2855 PseudoClass < ToggleButton , bool ? > ( IsCheckedProperty , c => c == false , ":unchecked" ) ;
2956 PseudoClass < ToggleButton , bool ? > ( IsCheckedProperty , c => c == null , ":indeterminate" ) ;
57+
58+ IsCheckedProperty . Changed . AddClassHandler < ToggleButton > ( ( x , e ) => x . OnIsCheckedChanged ( e ) ) ;
59+ }
60+
61+ /// <summary>
62+ /// Raised when a <see cref="ToggleButton"/> is checked.
63+ /// </summary>
64+ public event EventHandler < RoutedEventArgs > Checked
65+ {
66+ add => AddHandler ( CheckedEvent , value ) ;
67+ remove => RemoveHandler ( CheckedEvent , value ) ;
68+ }
69+
70+ /// <summary>
71+ /// Raised when a <see cref="ToggleButton"/> is unchecked.
72+ /// </summary>
73+ public event EventHandler < RoutedEventArgs > Unchecked
74+ {
75+ add => AddHandler ( UncheckedEvent , value ) ;
76+ remove => RemoveHandler ( UncheckedEvent , value ) ;
77+ }
78+
79+ /// <summary>
80+ /// Raised when a <see cref="ToggleButton"/> is neither checked nor unchecked.
81+ /// </summary>
82+ public event EventHandler < RoutedEventArgs > Indeterminate
83+ {
84+ add => AddHandler ( IndeterminateEvent , value ) ;
85+ remove => RemoveHandler ( IndeterminateEvent , value ) ;
3086 }
3187
88+ /// <summary>
89+ /// Gets or sets whether the <see cref="ToggleButton"/> is checked.
90+ /// </summary>
3291 public bool ? IsChecked
3392 {
34- get { return _isChecked ; }
35- set { SetAndRaise ( IsCheckedProperty , ref _isChecked , value ) ; }
93+ get => _isChecked ;
94+ set => SetAndRaise ( IsCheckedProperty , ref _isChecked , value ) ;
3695 }
3796
97+ /// <summary>
98+ /// Gets or sets a value that indicates whether the control supports three states.
99+ /// </summary>
38100 public bool IsThreeState
39101 {
40102 get => GetValue ( IsThreeStateProperty ) ;
@@ -47,18 +109,78 @@ protected override void OnClick()
47109 base . OnClick ( ) ;
48110 }
49111
112+ /// <summary>
113+ /// Toggles the <see cref="IsChecked"/> property.
114+ /// </summary>
50115 protected virtual void Toggle ( )
51116 {
52117 if ( IsChecked . HasValue )
118+ {
53119 if ( IsChecked . Value )
120+ {
54121 if ( IsThreeState )
122+ {
55123 IsChecked = null ;
124+ }
56125 else
126+ {
57127 IsChecked = false ;
128+ }
129+ }
58130 else
131+ {
59132 IsChecked = true ;
133+ }
134+ }
60135 else
136+ {
61137 IsChecked = false ;
138+ }
139+ }
140+
141+ /// <summary>
142+ /// Called when <see cref="IsChecked"/> becomes true.
143+ /// </summary>
144+ /// <param name="e">Event arguments for the routed event that is raised by the default implementation of this method.</param>
145+ protected virtual void OnChecked ( RoutedEventArgs e )
146+ {
147+ RaiseEvent ( e ) ;
148+ }
149+
150+ /// <summary>
151+ /// Called when <see cref="IsChecked"/> becomes false.
152+ /// </summary>
153+ /// <param name="e">Event arguments for the routed event that is raised by the default implementation of this method.</param>
154+ protected virtual void OnUnchecked ( RoutedEventArgs e )
155+ {
156+ RaiseEvent ( e ) ;
157+ }
158+
159+ /// <summary>
160+ /// Called when <see cref="IsChecked"/> becomes null.
161+ /// </summary>
162+ /// <param name="e">Event arguments for the routed event that is raised by the default implementation of this method.</param>
163+ protected virtual void OnIndeterminate ( RoutedEventArgs e )
164+ {
165+ RaiseEvent ( e ) ;
166+ }
167+
168+ private void OnIsCheckedChanged ( AvaloniaPropertyChangedEventArgs e )
169+ {
170+ var newValue = ( bool ? ) e . NewValue ;
171+
172+ switch ( newValue )
173+ {
174+ case true :
175+ OnChecked ( new RoutedEventArgs ( CheckedEvent ) ) ;
176+ break ;
177+ case false :
178+ OnUnchecked ( new RoutedEventArgs ( UncheckedEvent ) ) ;
179+ break ;
180+ default :
181+ OnIndeterminate ( new RoutedEventArgs ( IndeterminateEvent ) ) ;
182+ break ;
183+ }
62184 }
63185 }
64186}
0 commit comments