5 changed files with 390 additions and 199 deletions
@ -1,37 +1,40 @@ |
|||||
<UserControl xmlns="https://github.com/avaloniaui" |
<UserControl xmlns="https://github.com/avaloniaui" |
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
||||
x:Class="ControlCatalog.Pages.SplitButtonPage"> |
x:Class="ControlCatalog.Pages.SplitButtonPage"> |
||||
|
|
||||
|
<UserControl.Resources> |
||||
|
<MenuFlyout x:Key="SharedMenuFlyout" |
||||
|
Placement="Bottom"> |
||||
|
<MenuItem Header="Item 1"> |
||||
|
<MenuItem Header="Subitem 1" /> |
||||
|
<MenuItem Header="Subitem 2" /> |
||||
|
<MenuItem Header="Subitem 3" /> |
||||
|
</MenuItem> |
||||
|
<MenuItem Header="Item 2" |
||||
|
InputGesture="Ctrl+A" /> |
||||
|
<MenuItem Header="Item 3" /> |
||||
|
</MenuFlyout> |
||||
|
</UserControl.Resources> |
||||
|
|
||||
<StackPanel Orientation="Vertical" Spacing="4"> |
<StackPanel Orientation="Vertical" Spacing="4"> |
||||
<SplitButton> |
<SplitButton Flyout="{StaticResource SharedMenuFlyout}"> |
||||
<TextBlock Text="Content" /> |
<TextBlock Text="Content" /> |
||||
<SplitButton.Flyout> |
|
||||
<MenuFlyout> |
|
||||
<MenuItem Header="Item 1"> |
|
||||
<MenuItem Header="Subitem 1" /> |
|
||||
<MenuItem Header="Subitem 2" /> |
|
||||
<MenuItem Header="Subitem 3" /> |
|
||||
</MenuItem> |
|
||||
<MenuItem Header="Item 2" |
|
||||
InputGesture="Ctrl+A" /> |
|
||||
<MenuItem Header="Item 3" /> |
|
||||
</MenuFlyout> |
|
||||
</SplitButton.Flyout> |
|
||||
</SplitButton> |
</SplitButton> |
||||
<SplitButton |
<SplitButton IsEnabled="False" |
||||
IsEnabled="False"> |
Flyout="{StaticResource SharedMenuFlyout}"> |
||||
<TextBlock Text="Content" /> |
<TextBlock Text="Content" /> |
||||
<SplitButton.Flyout> |
|
||||
<MenuFlyout> |
|
||||
<MenuItem Header="Item 1"> |
|
||||
<MenuItem Header="Subitem 1" /> |
|
||||
<MenuItem Header="Subitem 2" /> |
|
||||
<MenuItem Header="Subitem 3" /> |
|
||||
</MenuItem> |
|
||||
<MenuItem Header="Item 2" |
|
||||
InputGesture="Ctrl+A" /> |
|
||||
<MenuItem Header="Item 3" /> |
|
||||
</MenuFlyout> |
|
||||
</SplitButton.Flyout> |
|
||||
</SplitButton> |
</SplitButton> |
||||
|
<ToggleSplitButton Flyout="{StaticResource SharedMenuFlyout}"> |
||||
|
<TextBlock Text="Content" /> |
||||
|
</ToggleSplitButton> |
||||
|
<ToggleSplitButton IsChecked="True" |
||||
|
Flyout="{StaticResource SharedMenuFlyout}"> |
||||
|
<TextBlock Text="Content" /> |
||||
|
</ToggleSplitButton> |
||||
|
<ToggleSplitButton IsChecked="True" |
||||
|
IsEnabled="False" |
||||
|
Flyout="{StaticResource SharedMenuFlyout}"> |
||||
|
<TextBlock Text="Content" /> |
||||
|
</ToggleSplitButton> |
||||
</StackPanel> |
</StackPanel> |
||||
</UserControl> |
</UserControl> |
||||
|
|||||
@ -1,25 +0,0 @@ |
|||||
using Avalonia.Interactivity; |
|
||||
|
|
||||
namespace Avalonia.Controls |
|
||||
{ |
|
||||
/// <summary>
|
|
||||
/// Provides event data for the <see cref="SplitButton.Click"/> event.
|
|
||||
/// </summary>
|
|
||||
public class SplitButtonClickEventArgs : RoutedEventArgs |
|
||||
{ |
|
||||
public SplitButtonClickEventArgs() |
|
||||
{ |
|
||||
} |
|
||||
|
|
||||
public SplitButtonClickEventArgs(RoutedEvent? routedEvent) |
|
||||
{ |
|
||||
RoutedEvent = routedEvent; |
|
||||
} |
|
||||
|
|
||||
public SplitButtonClickEventArgs(RoutedEvent? routedEvent, IInteractive? source) |
|
||||
{ |
|
||||
RoutedEvent = routedEvent; |
|
||||
Source = source; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -0,0 +1,147 @@ |
|||||
|
using System; |
||||
|
using Avalonia.Controls.Metadata; |
||||
|
using Avalonia.Controls.Primitives; |
||||
|
using Avalonia.Interactivity; |
||||
|
using Avalonia.Styling; |
||||
|
|
||||
|
namespace Avalonia.Controls |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// A button with primary and secondary parts that can each be pressed separately.
|
||||
|
/// The primary part behaves like a <see cref="ToggleButton"/> with two states and
|
||||
|
/// the secondary part opens a flyout.
|
||||
|
/// </summary>
|
||||
|
[PseudoClasses( |
||||
|
":disabled", |
||||
|
":secondaryButtonRight", |
||||
|
":secondaryButtonSpan", |
||||
|
":checkedFlyoutOpen", |
||||
|
":flyoutOpen", |
||||
|
":checkedTouchPressed", |
||||
|
":checked", |
||||
|
":checkedPrimaryPressed", |
||||
|
":checkedPrimaryPointerOver", |
||||
|
":checkedSecondaryPressed", |
||||
|
":checkedSecondaryPointerOver", |
||||
|
":touchPressed", |
||||
|
":primaryPressed", |
||||
|
":primaryPointerOver", |
||||
|
":secondaryPressed", |
||||
|
":secondaryPointerOver")] |
||||
|
public class ToggleSplitButton : SplitButton, IStyleable |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Raised when the <see cref="IsChecked"/> property value changes.
|
||||
|
/// </summary>
|
||||
|
public event EventHandler<RoutedEventArgs> IsCheckedChanged |
||||
|
{ |
||||
|
add => AddHandler(IsCheckedChangedEvent, value); |
||||
|
remove => RemoveHandler(IsCheckedChangedEvent, value); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Defines the <see cref="IsCheckedChanged"/> event.
|
||||
|
/// </summary>
|
||||
|
public static readonly RoutedEvent<RoutedEventArgs> IsCheckedChangedEvent = |
||||
|
RoutedEvent.Register<ToggleSplitButton, RoutedEventArgs>( |
||||
|
nameof(IsCheckedChanged), |
||||
|
RoutingStrategies.Bubble); |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Defines the <see cref="IsChecked"/> property.
|
||||
|
/// </summary>
|
||||
|
public static readonly StyledProperty<bool> IsCheckedProperty = |
||||
|
AvaloniaProperty.Register<ToggleSplitButton, bool>( |
||||
|
nameof(IsChecked)); |
||||
|
|
||||
|
////////////////////////////////////////////////////////////////////////
|
||||
|
//
|
||||
|
// Constructor / Destructors
|
||||
|
//
|
||||
|
////////////////////////////////////////////////////////////////////////
|
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Initializes a new instance of the <see cref="ToggleSplitButton"/> class.
|
||||
|
/// </summary>
|
||||
|
public ToggleSplitButton() |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
////////////////////////////////////////////////////////////////////////
|
||||
|
//
|
||||
|
// Properties
|
||||
|
//
|
||||
|
////////////////////////////////////////////////////////////////////////
|
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets or sets a value indicating whether the <see cref="ToggleSplitButton"/> is checked.
|
||||
|
/// </summary>
|
||||
|
public bool IsChecked |
||||
|
{ |
||||
|
get => GetValue(IsCheckedProperty); |
||||
|
set => SetValue(IsCheckedProperty, value); |
||||
|
} |
||||
|
|
||||
|
/// <inheritdoc/>
|
||||
|
internal override bool InternalIsChecked => IsChecked; |
||||
|
|
||||
|
/// <inheritdoc/>
|
||||
|
/// <remarks>
|
||||
|
/// Both <see cref="ToggleSplitButton"/> and <see cref="SplitButton"/> share
|
||||
|
/// the same exact default style.
|
||||
|
/// </remarks>
|
||||
|
Type IStyleable.StyleKey => typeof(SplitButton); |
||||
|
|
||||
|
////////////////////////////////////////////////////////////////////////
|
||||
|
//
|
||||
|
// Methods
|
||||
|
//
|
||||
|
////////////////////////////////////////////////////////////////////////
|
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Toggles the <see cref="IsChecked"/> property between true and false.
|
||||
|
/// </summary>
|
||||
|
protected void Toggle() |
||||
|
{ |
||||
|
IsChecked = !IsChecked; |
||||
|
} |
||||
|
|
||||
|
////////////////////////////////////////////////////////////////////////
|
||||
|
//
|
||||
|
// OnEvent Overridable Methods
|
||||
|
//
|
||||
|
////////////////////////////////////////////////////////////////////////
|
||||
|
|
||||
|
/// <inheritdoc/>
|
||||
|
protected override void OnPropertyChanged<T>(AvaloniaPropertyChangedEventArgs<T> e) |
||||
|
{ |
||||
|
if (e.Property == IsCheckedProperty) |
||||
|
{ |
||||
|
OnIsCheckedChanged(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Invokes the <see cref="IsCheckedChanged"/> event when the <see cref="IsChecked"/>
|
||||
|
/// property changes.
|
||||
|
/// </summary>
|
||||
|
protected virtual void OnIsCheckedChanged() |
||||
|
{ |
||||
|
if (_hasLoaded) |
||||
|
{ |
||||
|
var eventArgs = new RoutedEventArgs(IsCheckedChangedEvent); |
||||
|
RaiseEvent(eventArgs); |
||||
|
} |
||||
|
|
||||
|
UpdatePseudoClasses(); |
||||
|
} |
||||
|
|
||||
|
/// <inheritdoc/>
|
||||
|
protected override void OnClickPrimary(RoutedEventArgs e) |
||||
|
{ |
||||
|
Toggle(); |
||||
|
|
||||
|
base.OnClickPrimary(e); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
Loading…
Reference in new issue