Browse Source

Implement events for ToggleButton.

pull/3427/head
Dariusz Komosinski 6 years ago
parent
commit
35f26081c6
  1. 122
      src/Avalonia.Controls/Primitives/ToggleButton.cs
  2. 54
      tests/Avalonia.Controls.UnitTests/Primitives/ToggleButtonTests.cs

122
src/Avalonia.Controls/Primitives/ToggleButton.cs

@ -7,8 +7,14 @@ using Avalonia.Data;
namespace Avalonia.Controls.Primitives
{
/// <summary>
/// Represents a control that a user can select (check) or clear (uncheck). Base class for controls that can switch states.
/// </summary>
public class ToggleButton : Button
{
/// <summary>
/// Defines the <see cref="IsChecked"/> property.
/// </summary>
public static readonly DirectProperty<ToggleButton, bool?> IsCheckedProperty =
AvaloniaProperty.RegisterDirect<ToggleButton, bool?>(
nameof(IsChecked),
@ -17,9 +23,30 @@ namespace Avalonia.Controls.Primitives
unsetValue: null,
defaultBindingMode: BindingMode.TwoWay);
/// <summary>
/// Defines the <see cref="IsThreeState"/> property.
/// </summary>
public static readonly StyledProperty<bool> IsThreeStateProperty =
AvaloniaProperty.Register<ToggleButton, bool>(nameof(IsThreeState));
/// <summary>
/// Defines the <see cref="Checked"/> event.
/// </summary>
public static readonly RoutedEvent<RoutedEventArgs> CheckedEvent =
RoutedEvent.Register<ToggleButton, RoutedEventArgs>(nameof(Checked), RoutingStrategies.Bubble);
/// <summary>
/// Defines the <see cref="Unchecked"/> event.
/// </summary>
public static readonly RoutedEvent<RoutedEventArgs> UncheckedEvent =
RoutedEvent.Register<ToggleButton, RoutedEventArgs>(nameof(Unchecked), RoutingStrategies.Bubble);
/// <summary>
/// Defines the <see cref="Unchecked"/> event.
/// </summary>
public static readonly RoutedEvent<RoutedEventArgs> IndeterminateEvent =
RoutedEvent.Register<ToggleButton, RoutedEventArgs>(nameof(Indeterminate), RoutingStrategies.Bubble);
private bool? _isChecked = false;
static ToggleButton()
@ -27,14 +54,49 @@ namespace Avalonia.Controls.Primitives
PseudoClass<ToggleButton, bool?>(IsCheckedProperty, c => c == true, ":checked");
PseudoClass<ToggleButton, bool?>(IsCheckedProperty, c => c == false, ":unchecked");
PseudoClass<ToggleButton, bool?>(IsCheckedProperty, c => c == null, ":indeterminate");
IsCheckedProperty.Changed.AddClassHandler<ToggleButton>((x, e) => x.OnIsCheckedChanged(e));
}
/// <summary>
/// Raised when a <see cref="ToggleButton"/> is checked.
/// </summary>
public event EventHandler<RoutedEventArgs> Checked
{
add { AddHandler(CheckedEvent, value); }
remove { RemoveHandler(CheckedEvent, value); }
}
/// <summary>
/// Raised when a <see cref="ToggleButton"/> is unchecked.
/// </summary>
public event EventHandler<RoutedEventArgs> Unchecked
{
add { AddHandler(UncheckedEvent, value); }
remove { RemoveHandler(UncheckedEvent, value); }
}
/// <summary>
/// Raised when a <see cref="ToggleButton"/> is neither checked nor unchecked.
/// </summary>
public event EventHandler<RoutedEventArgs> Indeterminate
{
add { AddHandler(IndeterminateEvent, value); }
remove { RemoveHandler(IndeterminateEvent, value); }
}
/// <summary>
/// Gets or sets whether the <see cref="ToggleButton"/> is checked.
/// </summary>
public bool? IsChecked
{
get { return _isChecked; }
set { SetAndRaise(IsCheckedProperty, ref _isChecked, value); }
}
/// <summary>
/// Gets or sets a value that indicates whether the control supports three states.
/// </summary>
public bool IsThreeState
{
get => GetValue(IsThreeStateProperty);
@ -47,18 +109,78 @@ namespace Avalonia.Controls.Primitives
base.OnClick();
}
/// <summary>
/// Toggles the <see cref="IsChecked"/> property.
/// </summary>
protected virtual void Toggle()
{
if (IsChecked.HasValue)
{
if (IsChecked.Value)
{
if (IsThreeState)
{
IsChecked = null;
}
else
{
IsChecked = false;
}
}
else
{
IsChecked = true;
}
}
else
{
IsChecked = false;
}
}
/// <summary>
/// Called when <see cref="IsChecked"/> becomes true.
/// </summary>
/// <param name="e">Event arguments for the routed event that is raised by the default implementation of this method.</param>
protected virtual void OnChecked(RoutedEventArgs e)
{
RaiseEvent(e);
}
/// <summary>
/// Called when <see cref="IsChecked"/> becomes false.
/// </summary>
/// <param name="e">Event arguments for the routed event that is raised by the default implementation of this method.</param>
protected virtual void OnUnchecked(RoutedEventArgs e)
{
RaiseEvent(e);
}
/// <summary>
/// Called when <see cref="IsChecked"/> becomes null.
/// </summary>
/// <param name="e">Event arguments for the routed event that is raised by the default implementation of this method.</param>
protected virtual void OnIndeterminate(RoutedEventArgs e)
{
RaiseEvent(e);
}
private void OnIsCheckedChanged(AvaloniaPropertyChangedEventArgs e)
{
var newValue = (bool?)e.NewValue;
switch (newValue)
{
case true:
OnChecked(new RoutedEventArgs(CheckedEvent));
break;
case false:
OnUnchecked(new RoutedEventArgs(UncheckedEvent));
break;
default:
OnIndeterminate(new RoutedEventArgs(IndeterminateEvent));
break;
}
}
}
}

54
tests/Avalonia.Controls.UnitTests/Primitives/ToggleButtonTests.cs

@ -1,5 +1,4 @@
using Avalonia.Data;
using Avalonia.Markup.Data;
using Avalonia.UnitTests;
using Xunit;
@ -63,6 +62,54 @@ namespace Avalonia.Controls.Primitives.UnitTests
Assert.Null(threeStateButton.IsChecked);
}
[Fact]
public void ToggleButton_Events_Are_Raised_On_Is_Checked_Changes()
{
var threeStateButton = new ToggleButton();
bool checkedRaised = false;
threeStateButton.Checked += (_, __) => checkedRaised = true;
threeStateButton.IsChecked = true;
Assert.True(checkedRaised);
bool uncheckedRaised = false;
threeStateButton.Unchecked += (_, __) => uncheckedRaised = true;
threeStateButton.IsChecked = false;
Assert.True(uncheckedRaised);
bool indeterminateRaised = false;
threeStateButton.Indeterminate += (_, __) => indeterminateRaised = true;
threeStateButton.IsChecked = null;
Assert.True(indeterminateRaised);
}
[Fact]
public void ToggleButton_Events_Are_Raised_When_Toggling()
{
var threeStateButton = new TestToggleButton { IsThreeState = true };
bool checkedRaised = false;
threeStateButton.Checked += (_, __) => checkedRaised = true;
threeStateButton.Toggle();
Assert.True(checkedRaised);
bool indeterminateRaised = false;
threeStateButton.Indeterminate += (_, __) => indeterminateRaised = true;
threeStateButton.Toggle();
Assert.True(indeterminateRaised);
bool uncheckedRaised = false;
threeStateButton.Unchecked += (_, __) => uncheckedRaised = true;
threeStateButton.Toggle();
Assert.True(uncheckedRaised);
}
private class Class1 : NotifyingBase
{
private bool _foo;
@ -80,5 +127,10 @@ namespace Avalonia.Controls.Primitives.UnitTests
set { nullableFoo = value; RaisePropertyChanged(); }
}
}
private class TestToggleButton : ToggleButton
{
public new void Toggle() => base.Toggle();
}
}
}

Loading…
Cancel
Save