committed by
GitHub
16 changed files with 1420 additions and 58 deletions
@ -1,45 +0,0 @@ |
|||||
<UserControl xmlns="https://github.com/avaloniaui" |
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
|
||||
x:Class="ControlCatalog.Pages.ButtonPage"> |
|
||||
<StackPanel Orientation="Vertical" Spacing="4"> |
|
||||
<TextBlock Classes="h2">A button control</TextBlock> |
|
||||
|
|
||||
<StackPanel Orientation="Horizontal" |
|
||||
Margin="0,16,0,0" |
|
||||
HorizontalAlignment="Center" |
|
||||
Spacing="16"> |
|
||||
<StackPanel Orientation="Vertical" Spacing="8" Width="200"> |
|
||||
<Button>Standard _XAML Button</Button> |
|
||||
<Button Foreground="White">Foreground</Button> |
|
||||
<Button Background="{DynamicResource SystemAccentColor}">Background</Button> |
|
||||
<Button IsEnabled="False">Disabled</Button> |
|
||||
<Button Content="Re-themed"> |
|
||||
<Button.Styles> |
|
||||
<Style> |
|
||||
<Style.Resources> |
|
||||
<SolidColorBrush x:Key="ThemeBorderMidBrush">Red</SolidColorBrush> |
|
||||
<SolidColorBrush x:Key="ThemeControlHighBrush">DarkRed</SolidColorBrush> |
|
||||
<SolidColorBrush x:Key="ButtonBorderBrush">Red</SolidColorBrush> |
|
||||
<SolidColorBrush x:Key="ButtonBackground">DarkRed</SolidColorBrush> |
|
||||
<SolidColorBrush x:Key="ButtonBackgroundPointerOver">Red</SolidColorBrush> |
|
||||
<SolidColorBrush x:Key="ButtonBackgroundPressed">OrangeRed</SolidColorBrush> |
|
||||
</Style.Resources> |
|
||||
</Style> |
|
||||
</Button.Styles> |
|
||||
</Button> |
|
||||
<RepeatButton Name="RepeatButton"> |
|
||||
<TextBlock Name="RepeatButtonTextBlock" Text="Repeat Button: 0" /> |
|
||||
</RepeatButton> |
|
||||
<ToggleButton Content="Toggle Button"/> |
|
||||
</StackPanel> |
|
||||
|
|
||||
<StackPanel Orientation="Vertical" Spacing="8" Width="150"> |
|
||||
<Button BorderThickness="0">No Border</Button> |
|
||||
<Button BorderBrush="{DynamicResource SystemAccentColor}">Border Color</Button> |
|
||||
<Button BorderBrush="{DynamicResource SystemAccentColor}" BorderThickness="4">Thick Border</Button> |
|
||||
<Button BorderBrush="{DynamicResource SystemAccentColor}" BorderThickness="4" IsEnabled="False">Disabled</Button> |
|
||||
<Button BorderBrush="{DynamicResource SystemAccentColor}" KeyboardNavigation.IsTabStop="False">IsTabStop=False</Button> |
|
||||
</StackPanel> |
|
||||
</StackPanel> |
|
||||
</StackPanel> |
|
||||
</UserControl> |
|
||||
@ -0,0 +1,224 @@ |
|||||
|
<UserControl xmlns="https://github.com/avaloniaui" |
||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
||||
|
x:Class="ControlCatalog.Pages.ButtonsPage"> |
||||
|
|
||||
|
<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> |
||||
|
|
||||
|
<UserControl.Styles > |
||||
|
|
||||
|
<Style Selector="Border.header-border"> |
||||
|
<Setter Property="Background"> |
||||
|
<Setter.Value> |
||||
|
<SolidColorBrush Color="Gray" Opacity="0.5" /> |
||||
|
</Setter.Value> |
||||
|
</Setter> |
||||
|
<Setter Property="BorderBrush" Value="Gray" /> |
||||
|
<Setter Property="BorderThickness" Value="0.5" /> |
||||
|
<Setter Property="CornerRadius" Value="5,5,0,0" /> |
||||
|
<Setter Property="MaxWidth" Value="450" /> |
||||
|
<Setter Property="Padding" Value="10" /> |
||||
|
</Style> |
||||
|
|
||||
|
<Style Selector="TextBlock.header"> |
||||
|
<Setter Property="FontSize" Value="18" /> |
||||
|
<Setter Property="FontWeight" Value="Bold" /> |
||||
|
</Style> |
||||
|
|
||||
|
<Style Selector="Border.thin"> |
||||
|
<Setter Property="BorderBrush" Value="Gray" /> |
||||
|
<Setter Property="BorderThickness" Value="0.5" /> |
||||
|
<Setter Property="CornerRadius" Value="0,0,5,5" /> |
||||
|
<Setter Property="Margin" Value="0,0,0,15" /> |
||||
|
</Style> |
||||
|
|
||||
|
</UserControl.Styles> |
||||
|
|
||||
|
<!-- Styles and overall page design based on AcrylicPage --> |
||||
|
|
||||
|
<StackPanel Orientation="Vertical" |
||||
|
Width="450"> |
||||
|
|
||||
|
<!-- Button --> |
||||
|
<Border Classes="header-border"> |
||||
|
<StackPanel Orientation="Vertical" |
||||
|
Spacing="4"> |
||||
|
<TextBlock Text="Button" Classes="header" /> |
||||
|
<TextBlock TextWrapping="Wrap">A standard button control</TextBlock> |
||||
|
</StackPanel> |
||||
|
</Border> |
||||
|
|
||||
|
<Border Classes="thin" |
||||
|
Padding="15"> |
||||
|
<StackPanel Orientation="Horizontal" |
||||
|
HorizontalAlignment="Center" |
||||
|
Spacing="10"> |
||||
|
<StackPanel Orientation="Vertical" |
||||
|
Spacing="8" |
||||
|
Width="200"> |
||||
|
<Button>Standard _XAML Button</Button> |
||||
|
<Button Foreground="White">Foreground</Button> |
||||
|
<Button Background="{DynamicResource SystemAccentColor}">Background</Button> |
||||
|
<Button IsEnabled="False">Disabled</Button> |
||||
|
<Button Content="Re-themed"> |
||||
|
<Button.Styles> |
||||
|
<Style> |
||||
|
<Style.Resources> |
||||
|
<SolidColorBrush x:Key="ThemeBorderMidBrush">Red</SolidColorBrush> |
||||
|
<SolidColorBrush x:Key="ThemeControlHighBrush">DarkRed</SolidColorBrush> |
||||
|
<SolidColorBrush x:Key="ButtonBorderBrush">Red</SolidColorBrush> |
||||
|
<SolidColorBrush x:Key="ButtonBackground">DarkRed</SolidColorBrush> |
||||
|
<SolidColorBrush x:Key="ButtonBackgroundPointerOver">Red</SolidColorBrush> |
||||
|
<SolidColorBrush x:Key="ButtonBackgroundPressed">OrangeRed</SolidColorBrush> |
||||
|
<SolidColorBrush x:Key="ButtonForeground">White</SolidColorBrush> |
||||
|
<SolidColorBrush x:Key="ButtonForegroundPointerOver">Black</SolidColorBrush> |
||||
|
<SolidColorBrush x:Key="ButtonForegroundPressed">Black</SolidColorBrush> |
||||
|
</Style.Resources> |
||||
|
</Style> |
||||
|
</Button.Styles> |
||||
|
</Button> |
||||
|
</StackPanel> |
||||
|
|
||||
|
<StackPanel Orientation="Vertical" |
||||
|
Spacing="8" |
||||
|
Width="200"> |
||||
|
<Button BorderThickness="0">No Border</Button> |
||||
|
<Button BorderBrush="{DynamicResource SystemAccentColor}">Border Color</Button> |
||||
|
<Button BorderBrush="{DynamicResource SystemAccentColor}" |
||||
|
BorderThickness="4">Thick Border</Button> |
||||
|
<Button BorderBrush="{DynamicResource SystemAccentColor}" |
||||
|
BorderThickness="4" |
||||
|
IsEnabled="False">Disabled</Button> |
||||
|
<Button BorderBrush="{DynamicResource SystemAccentColor}" |
||||
|
KeyboardNavigation.IsTabStop="False">IsTabStop=False</Button> |
||||
|
</StackPanel> |
||||
|
</StackPanel> |
||||
|
</Border> |
||||
|
|
||||
|
<!-- ToggleButton --> |
||||
|
<Border Classes="header-border"> |
||||
|
<StackPanel Orientation="Vertical" |
||||
|
Spacing="4"> |
||||
|
<TextBlock Text="ToggleButton" |
||||
|
Classes="header" /> |
||||
|
<TextBlock TextWrapping="Wrap">A button control with multiple states: checked, unchecked or indeterminate.</TextBlock> |
||||
|
</StackPanel> |
||||
|
</Border> |
||||
|
|
||||
|
<Border Classes="thin" |
||||
|
Padding="15"> |
||||
|
<StackPanel Orientation="Vertical" |
||||
|
Spacing="8"> |
||||
|
<ToggleButton Content="Toggle Button" /> |
||||
|
</StackPanel> |
||||
|
</Border> |
||||
|
|
||||
|
<!-- RepeatButton --> |
||||
|
<Border Classes="header-border"> |
||||
|
<StackPanel Orientation="Vertical" |
||||
|
Spacing="4"> |
||||
|
<TextBlock Text="RepeatButton" |
||||
|
Classes="header" /> |
||||
|
<TextBlock TextWrapping="Wrap">A button control that raises its Click event repeatedly when it is pressed and held.</TextBlock> |
||||
|
</StackPanel> |
||||
|
</Border> |
||||
|
|
||||
|
<Border Classes="thin" |
||||
|
Padding="15"> |
||||
|
<StackPanel Orientation="Vertical" |
||||
|
Spacing="8"> |
||||
|
<RepeatButton Name="RepeatButton"> |
||||
|
<TextBlock Name="RepeatButtonTextBlock" |
||||
|
Text="Repeat Button: 0" /> |
||||
|
</RepeatButton> |
||||
|
</StackPanel> |
||||
|
</Border> |
||||
|
|
||||
|
<!-- SplitButton --> |
||||
|
<Border Classes="header-border"> |
||||
|
<StackPanel Orientation="Vertical" |
||||
|
Spacing="4"> |
||||
|
<TextBlock Text="SplitButton" |
||||
|
Classes="header" /> |
||||
|
<TextBlock TextWrapping="Wrap">A button with primary and secondary parts that can each be pressed separately. The primary part behaves like a Button and the secondary part opens a flyout.</TextBlock> |
||||
|
</StackPanel> |
||||
|
</Border> |
||||
|
|
||||
|
<Border Classes="thin" |
||||
|
Padding="15"> |
||||
|
<StackPanel Orientation="Vertical" |
||||
|
Spacing="8"> |
||||
|
<SplitButton Flyout="{StaticResource SharedMenuFlyout}"> |
||||
|
<TextBlock Text="Content" /> |
||||
|
</SplitButton> |
||||
|
<SplitButton IsEnabled="False" |
||||
|
Flyout="{StaticResource SharedMenuFlyout}"> |
||||
|
<TextBlock Text="Disabled" /> |
||||
|
</SplitButton> |
||||
|
<SplitButton Flyout="{StaticResource SharedMenuFlyout}" |
||||
|
Content="Re-themed"> |
||||
|
<SplitButton.Styles> |
||||
|
<Style> |
||||
|
<Style.Resources> |
||||
|
<x:Double x:Key="SplitButtonSeparatorWidth">1.5</x:Double> |
||||
|
<Thickness x:Key="SplitButtonBorderThemeThickness">2</Thickness> |
||||
|
<SolidColorBrush x:Key="SplitButtonBorderBrush">Red</SolidColorBrush> |
||||
|
<SolidColorBrush x:Key="SplitButtonBorderBrushPointerOver">Red</SolidColorBrush> |
||||
|
<SolidColorBrush x:Key="SplitButtonBorderBrushPressed">Red</SolidColorBrush> |
||||
|
<SolidColorBrush x:Key="SplitButtonBackground">DarkRed</SolidColorBrush> |
||||
|
<SolidColorBrush x:Key="SplitButtonBackgroundPointerOver">Red</SolidColorBrush> |
||||
|
<SolidColorBrush x:Key="SplitButtonBackgroundPressed">OrangeRed</SolidColorBrush> |
||||
|
<SolidColorBrush x:Key="SplitButtonForeground">White</SolidColorBrush> |
||||
|
<SolidColorBrush x:Key="SplitButtonForegroundPointerOver">Black</SolidColorBrush> |
||||
|
<SolidColorBrush x:Key="SplitButtonForegroundPressed">Black</SolidColorBrush> |
||||
|
</Style.Resources> |
||||
|
</Style> |
||||
|
</SplitButton.Styles> |
||||
|
</SplitButton> |
||||
|
</StackPanel> |
||||
|
</Border> |
||||
|
|
||||
|
<!-- ToggleSplitButton --> |
||||
|
<Border Classes="header-border"> |
||||
|
<StackPanel Orientation="Vertical" |
||||
|
Spacing="4"> |
||||
|
<TextBlock Text="ToggleSplitButton" |
||||
|
Classes="header" /> |
||||
|
<TextBlock TextWrapping="Wrap">A button with primary and secondary parts that can each be pressed separately. The primary part behaves like a ToggleButton with two states and the secondary part opens a flyout.</TextBlock> |
||||
|
</StackPanel> |
||||
|
</Border> |
||||
|
|
||||
|
<Border Classes="thin" |
||||
|
Padding="15"> |
||||
|
<StackPanel Orientation="Vertical" |
||||
|
Spacing="8"> |
||||
|
<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="Disabled" /> |
||||
|
</ToggleSplitButton> |
||||
|
</StackPanel> |
||||
|
</Border> |
||||
|
|
||||
|
</StackPanel> |
||||
|
</UserControl> |
||||
@ -0,0 +1,485 @@ |
|||||
|
using System; |
||||
|
using System.Windows.Input; |
||||
|
using Avalonia.Controls.Metadata; |
||||
|
using Avalonia.Controls.Mixins; |
||||
|
using Avalonia.Controls.Primitives; |
||||
|
using Avalonia.Input; |
||||
|
using Avalonia.Interactivity; |
||||
|
using Avalonia.LogicalTree; |
||||
|
|
||||
|
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="Button"/> and the secondary part opens a flyout.
|
||||
|
/// </summary>
|
||||
|
[PseudoClasses(pcFlyoutOpen, pcPressed)] |
||||
|
public class SplitButton : ContentControl, ICommandSource |
||||
|
{ |
||||
|
protected const string pcChecked = ":checked"; |
||||
|
protected const string pcPressed = ":pressed"; |
||||
|
protected const string pcFlyoutOpen = ":flyout-open"; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Raised when the user presses the primary part of the <see cref="SplitButton"/>.
|
||||
|
/// </summary>
|
||||
|
public event EventHandler<RoutedEventArgs> Click |
||||
|
{ |
||||
|
add => AddHandler(ClickEvent, value); |
||||
|
remove => RemoveHandler(ClickEvent, value); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Defines the <see cref="Click"/> event.
|
||||
|
/// </summary>
|
||||
|
public static readonly RoutedEvent<RoutedEventArgs> ClickEvent = |
||||
|
RoutedEvent.Register<SplitButton, RoutedEventArgs>(nameof(Click), RoutingStrategies.Bubble); |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Defines the <see cref="Command"/> property.
|
||||
|
/// </summary>
|
||||
|
public static readonly DirectProperty<SplitButton, ICommand?> CommandProperty = |
||||
|
Button.CommandProperty.AddOwner<SplitButton>( |
||||
|
splitButton => splitButton.Command, |
||||
|
(splitButton, command) => splitButton.Command = command); |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Defines the <see cref="CommandParameter"/> property.
|
||||
|
/// </summary>
|
||||
|
public static readonly StyledProperty<object?> CommandParameterProperty = |
||||
|
Button.CommandParameterProperty.AddOwner<SplitButton>(); |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Defines the <see cref="Flyout"/> property
|
||||
|
/// </summary>
|
||||
|
public static readonly StyledProperty<FlyoutBase?> FlyoutProperty = |
||||
|
Button.FlyoutProperty.AddOwner<SplitButton>(); |
||||
|
|
||||
|
private ICommand? _Command; |
||||
|
|
||||
|
private Button? _primaryButton = null; |
||||
|
private Button? _secondaryButton = null; |
||||
|
|
||||
|
private bool _commandCanExecute = true; |
||||
|
private bool _isAttachedToLogicalTree = false; |
||||
|
private bool _isFlyoutOpen = false; |
||||
|
private bool _isKeyboardPressed = false; |
||||
|
|
||||
|
private IDisposable? _flyoutPropertyChangedDisposable; |
||||
|
|
||||
|
////////////////////////////////////////////////////////////////////////
|
||||
|
// Constructor / Destructors
|
||||
|
////////////////////////////////////////////////////////////////////////
|
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Initializes a new instance of the <see cref="SplitButton"/> class.
|
||||
|
/// </summary>
|
||||
|
public SplitButton() |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
////////////////////////////////////////////////////////////////////////
|
||||
|
// Properties
|
||||
|
////////////////////////////////////////////////////////////////////////
|
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets or sets the <see cref="ICommand"/> invoked when the primary part is pressed.
|
||||
|
/// </summary>
|
||||
|
public ICommand? Command |
||||
|
{ |
||||
|
get => _Command; |
||||
|
set => SetAndRaise(CommandProperty, ref _Command, value); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets or sets a parameter to be passed to the <see cref="Command"/>.
|
||||
|
/// </summary>
|
||||
|
public object? CommandParameter |
||||
|
{ |
||||
|
get => GetValue(CommandParameterProperty); |
||||
|
set => SetValue(CommandParameterProperty, value); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets or sets the <see cref="FlyoutBase"/> that is shown when the secondary part is pressed.
|
||||
|
/// </summary>
|
||||
|
public FlyoutBase? Flyout |
||||
|
{ |
||||
|
get => GetValue(FlyoutProperty); |
||||
|
set => SetValue(FlyoutProperty, value); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets a value indicating whether the button is currently checked.
|
||||
|
/// </summary>
|
||||
|
/// <remarks>
|
||||
|
/// This property exists only for the derived <see cref="ToggleSplitButton"/> and is
|
||||
|
/// unused (set to false) within <see cref="SplitButton"/>. Doing this allows the
|
||||
|
/// two controls to share a default style.
|
||||
|
/// </remarks>
|
||||
|
internal virtual bool InternalIsChecked => false; |
||||
|
|
||||
|
/// <inheritdoc/>
|
||||
|
protected override bool IsEnabledCore => base.IsEnabledCore && _commandCanExecute; |
||||
|
|
||||
|
////////////////////////////////////////////////////////////////////////
|
||||
|
// Methods
|
||||
|
////////////////////////////////////////////////////////////////////////
|
||||
|
|
||||
|
/// <inheritdoc/>
|
||||
|
void ICommandSource.CanExecuteChanged(object sender, EventArgs e) => this.CanExecuteChanged(sender, e); |
||||
|
|
||||
|
/// <inheritdoc cref="ICommandSource.CanExecuteChanged"/>
|
||||
|
private void CanExecuteChanged(object? sender, EventArgs e) |
||||
|
{ |
||||
|
var canExecute = Command == null || Command.CanExecute(CommandParameter); |
||||
|
|
||||
|
if (canExecute != _commandCanExecute) |
||||
|
{ |
||||
|
_commandCanExecute = canExecute; |
||||
|
UpdateIsEffectivelyEnabled(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Updates the visual state of the control by applying latest PseudoClasses.
|
||||
|
/// </summary>
|
||||
|
protected void UpdatePseudoClasses() |
||||
|
{ |
||||
|
PseudoClasses.Set(pcFlyoutOpen, _isFlyoutOpen); |
||||
|
PseudoClasses.Set(pcPressed, _isKeyboardPressed); |
||||
|
PseudoClasses.Set(pcChecked, InternalIsChecked); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Opens the secondary button's flyout.
|
||||
|
/// </summary>
|
||||
|
protected void OpenFlyout() |
||||
|
{ |
||||
|
if (Flyout != null) |
||||
|
{ |
||||
|
Flyout.ShowAt(this); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Closes the secondary button's flyout.
|
||||
|
/// </summary>
|
||||
|
protected void CloseFlyout() |
||||
|
{ |
||||
|
if (Flyout != null) |
||||
|
{ |
||||
|
Flyout.Hide(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Registers all flyout events.
|
||||
|
/// </summary>
|
||||
|
/// <param name="flyout">The flyout to connect events to.</param>
|
||||
|
private void RegisterFlyoutEvents(FlyoutBase? flyout) |
||||
|
{ |
||||
|
if (flyout != null) |
||||
|
{ |
||||
|
flyout.Opened += Flyout_Opened; |
||||
|
flyout.Closed += Flyout_Closed; |
||||
|
|
||||
|
_flyoutPropertyChangedDisposable = flyout.GetPropertyChangedObservable(FlyoutBase.PlacementProperty).Subscribe(Flyout_PlacementPropertyChanged); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Explicitly unregisters all flyout events.
|
||||
|
/// </summary>
|
||||
|
/// <param name="flyout">The flyout to disconnect events from.</param>
|
||||
|
private void UnregisterFlyoutEvents(FlyoutBase? flyout) |
||||
|
{ |
||||
|
if (flyout != null) |
||||
|
{ |
||||
|
flyout.Opened -= Flyout_Opened; |
||||
|
flyout.Closed -= Flyout_Closed; |
||||
|
|
||||
|
_flyoutPropertyChangedDisposable?.Dispose(); |
||||
|
_flyoutPropertyChangedDisposable = null; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Explicitly unregisters all events related to the two buttons in OnApplyTemplate().
|
||||
|
/// </summary>
|
||||
|
private void UnregisterEvents() |
||||
|
{ |
||||
|
if (_primaryButton != null) |
||||
|
{ |
||||
|
_primaryButton.Click -= PrimaryButton_Click; |
||||
|
} |
||||
|
|
||||
|
if (_secondaryButton != null) |
||||
|
{ |
||||
|
_secondaryButton.Click -= SecondaryButton_Click; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
////////////////////////////////////////////////////////////////////////
|
||||
|
// OnEvent Overridable Methods
|
||||
|
////////////////////////////////////////////////////////////////////////
|
||||
|
|
||||
|
/// <inheritdoc/>
|
||||
|
protected override void OnApplyTemplate(TemplateAppliedEventArgs e) |
||||
|
{ |
||||
|
UnregisterEvents(); |
||||
|
UnregisterFlyoutEvents(Flyout); |
||||
|
|
||||
|
_primaryButton = e.NameScope.Find<Button>("PART_PrimaryButton"); |
||||
|
_secondaryButton = e.NameScope.Find<Button>("PART_SecondaryButton"); |
||||
|
|
||||
|
if (_primaryButton != null) |
||||
|
{ |
||||
|
_primaryButton.Click += PrimaryButton_Click; |
||||
|
} |
||||
|
|
||||
|
if (_secondaryButton != null) |
||||
|
{ |
||||
|
_secondaryButton.Click += SecondaryButton_Click; |
||||
|
} |
||||
|
|
||||
|
RegisterFlyoutEvents(Flyout); |
||||
|
UpdatePseudoClasses(); |
||||
|
} |
||||
|
|
||||
|
/// <inheritdoc/>
|
||||
|
protected override void OnAttachedToLogicalTree(LogicalTreeAttachmentEventArgs e) |
||||
|
{ |
||||
|
base.OnAttachedToLogicalTree(e); |
||||
|
|
||||
|
if (Command != null) |
||||
|
{ |
||||
|
Command.CanExecuteChanged += CanExecuteChanged; |
||||
|
CanExecuteChanged(this, EventArgs.Empty); |
||||
|
} |
||||
|
|
||||
|
_isAttachedToLogicalTree = true; |
||||
|
} |
||||
|
|
||||
|
/// <inheritdoc/>
|
||||
|
protected override void OnDetachedFromLogicalTree(LogicalTreeAttachmentEventArgs e) |
||||
|
{ |
||||
|
base.OnDetachedFromLogicalTree(e); |
||||
|
|
||||
|
if (Command != null) |
||||
|
{ |
||||
|
Command.CanExecuteChanged -= CanExecuteChanged; |
||||
|
} |
||||
|
|
||||
|
_isAttachedToLogicalTree = false; |
||||
|
} |
||||
|
|
||||
|
/// <inheritdoc/>
|
||||
|
protected override void OnPropertyChanged<T>(AvaloniaPropertyChangedEventArgs<T> e) |
||||
|
{ |
||||
|
if (e.Property == CommandProperty) |
||||
|
{ |
||||
|
if (_isAttachedToLogicalTree) |
||||
|
{ |
||||
|
// Must unregister events here while a reference to the old command still exists
|
||||
|
if (e.OldValue.GetValueOrDefault() is ICommand oldCommand) |
||||
|
{ |
||||
|
oldCommand.CanExecuteChanged -= CanExecuteChanged; |
||||
|
} |
||||
|
|
||||
|
if (e.NewValue.GetValueOrDefault() is ICommand newCommand) |
||||
|
{ |
||||
|
newCommand.CanExecuteChanged += CanExecuteChanged; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
CanExecuteChanged(this, EventArgs.Empty); |
||||
|
} |
||||
|
else if (e.Property == CommandParameterProperty) |
||||
|
{ |
||||
|
CanExecuteChanged(this, EventArgs.Empty); |
||||
|
} |
||||
|
else if (e.Property == FlyoutProperty) |
||||
|
{ |
||||
|
var oldFlyout = e.OldValue.GetValueOrDefault() as FlyoutBase; |
||||
|
var newFlyout = e.NewValue.GetValueOrDefault() as FlyoutBase; |
||||
|
|
||||
|
// If flyout is changed while one is already open, make sure we
|
||||
|
// close the old one first
|
||||
|
// This is the same behavior as Button
|
||||
|
if (oldFlyout != null && |
||||
|
oldFlyout.IsOpen) |
||||
|
{ |
||||
|
oldFlyout.Hide(); |
||||
|
} |
||||
|
|
||||
|
// Must unregister events here while a reference to the old flyout still exists
|
||||
|
if (oldFlyout != null) |
||||
|
{ |
||||
|
UnregisterFlyoutEvents(oldFlyout); |
||||
|
} |
||||
|
|
||||
|
if (newFlyout != null) |
||||
|
{ |
||||
|
RegisterFlyoutEvents(newFlyout); |
||||
|
} |
||||
|
|
||||
|
UpdatePseudoClasses(); |
||||
|
} |
||||
|
|
||||
|
base.OnPropertyChanged(e); |
||||
|
} |
||||
|
|
||||
|
/// <inheritdoc/>
|
||||
|
protected override void OnKeyDown(KeyEventArgs e) |
||||
|
{ |
||||
|
var key = e.Key; |
||||
|
|
||||
|
if (key == Key.Space || key == Key.Enter) // Key.GamepadA is not currently supported
|
||||
|
{ |
||||
|
_isKeyboardPressed = true; |
||||
|
UpdatePseudoClasses(); |
||||
|
} |
||||
|
|
||||
|
base.OnKeyDown(e); |
||||
|
} |
||||
|
|
||||
|
/// <inheritdoc/>
|
||||
|
protected override void OnKeyUp(KeyEventArgs e) |
||||
|
{ |
||||
|
var key = e.Key; |
||||
|
|
||||
|
if (key == Key.Space || key == Key.Enter) // Key.GamepadA is not currently supported
|
||||
|
{ |
||||
|
_isKeyboardPressed = false; |
||||
|
UpdatePseudoClasses(); |
||||
|
|
||||
|
// Consider this a click on the primary button
|
||||
|
if (IsEffectivelyEnabled) |
||||
|
{ |
||||
|
OnClickPrimary(null); |
||||
|
e.Handled = true; |
||||
|
} |
||||
|
} |
||||
|
else if (key == Key.Down && e.KeyModifiers.HasAllFlags(KeyModifiers.Alt) && IsEffectivelyEnabled) |
||||
|
{ |
||||
|
OpenFlyout(); |
||||
|
e.Handled = true; |
||||
|
} |
||||
|
else if (key == Key.F4 && IsEffectivelyEnabled) |
||||
|
{ |
||||
|
OpenFlyout(); |
||||
|
e.Handled = true; |
||||
|
} |
||||
|
else if (e.Key == Key.Escape && _isFlyoutOpen) |
||||
|
{ |
||||
|
// If Flyout doesn't have focusable content, close the flyout here
|
||||
|
// This is the same behavior as Button
|
||||
|
CloseFlyout(); |
||||
|
e.Handled = true; |
||||
|
} |
||||
|
|
||||
|
base.OnKeyUp(e); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Invokes the <see cref="Click"/> event when the primary button part is clicked.
|
||||
|
/// </summary>
|
||||
|
/// <param name="e">The event args from the internal Click event.</param>
|
||||
|
protected virtual void OnClickPrimary(RoutedEventArgs? e) |
||||
|
{ |
||||
|
// Note: It is not currently required to check enabled status; however, this is a failsafe
|
||||
|
if (IsEffectivelyEnabled) |
||||
|
{ |
||||
|
var eventArgs = new RoutedEventArgs(ClickEvent); |
||||
|
RaiseEvent(eventArgs); |
||||
|
|
||||
|
if (!eventArgs.Handled && Command?.CanExecute(CommandParameter) == true) |
||||
|
{ |
||||
|
Command.Execute(CommandParameter); |
||||
|
eventArgs.Handled = true; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Invoked when the secondary button part is clicked.
|
||||
|
/// </summary>
|
||||
|
/// <param name="e">The event args from the internal Click event.</param>
|
||||
|
protected virtual void OnClickSecondary(RoutedEventArgs? e) |
||||
|
{ |
||||
|
// Note: It is not currently required to check enabled status; however, this is a failsafe
|
||||
|
if (IsEffectivelyEnabled) |
||||
|
{ |
||||
|
OpenFlyout(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
////////////////////////////////////////////////////////////////////////
|
||||
|
// Event Handling
|
||||
|
////////////////////////////////////////////////////////////////////////
|
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Event handler for when the internal primary button part is pressed.
|
||||
|
/// </summary>
|
||||
|
private void PrimaryButton_Click(object? sender, RoutedEventArgs e) |
||||
|
{ |
||||
|
// Handle internal button click, so it won't bubble outside together with SplitButton.ClickEvent.
|
||||
|
e.Handled = true; |
||||
|
OnClickPrimary(e); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Event handler for when the internal secondary button part is pressed.
|
||||
|
/// </summary>
|
||||
|
private void SecondaryButton_Click(object? sender, RoutedEventArgs e) |
||||
|
{ |
||||
|
// Handle internal button click, so it won't bubble outside.
|
||||
|
e.Handled = true; |
||||
|
OnClickSecondary(e); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Called when the <see cref="FlyoutBase.Placement"/> property changes.
|
||||
|
/// </summary>
|
||||
|
private void Flyout_PlacementPropertyChanged(AvaloniaPropertyChangedEventArgs e) |
||||
|
{ |
||||
|
UpdatePseudoClasses(); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Event handler for when the split button's flyout is opened.
|
||||
|
/// </summary>
|
||||
|
private void Flyout_Opened(object? sender, EventArgs e) |
||||
|
{ |
||||
|
var flyout = sender as FlyoutBase; |
||||
|
|
||||
|
// It is possible to share flyouts among multiple controls including SplitButton.
|
||||
|
// This can cause a problem here since all controls that share a flyout receive
|
||||
|
// the same Opened/Closed events at the same time.
|
||||
|
// For SplitButton that means they all would be updating their pseudoclasses accordingly.
|
||||
|
// In other words, all SplitButtons with a shared Flyout would have the backgrounds changed together.
|
||||
|
// To fix this, only continue here if the Flyout target matches this SplitButton instance.
|
||||
|
if (object.ReferenceEquals(flyout?.Target, this)) |
||||
|
{ |
||||
|
_isFlyoutOpen = true; |
||||
|
UpdatePseudoClasses(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Event handler for when the split button's flyout is closed.
|
||||
|
/// </summary>
|
||||
|
private void Flyout_Closed(object? sender, EventArgs e) |
||||
|
{ |
||||
|
var flyout = sender as FlyoutBase; |
||||
|
|
||||
|
// See comments in Flyout_Opened
|
||||
|
if (object.ReferenceEquals(flyout?.Target, this)) |
||||
|
{ |
||||
|
_isFlyoutOpen = false; |
||||
|
UpdatePseudoClasses(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,125 @@ |
|||||
|
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(pcChecked)] |
||||
|
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() |
||||
|
{ |
||||
|
// IsLoaded check
|
||||
|
if (Parent is not null) |
||||
|
{ |
||||
|
var eventArgs = new RoutedEventArgs(IsCheckedChangedEvent); |
||||
|
RaiseEvent(eventArgs); |
||||
|
} |
||||
|
|
||||
|
UpdatePseudoClasses(); |
||||
|
} |
||||
|
|
||||
|
/// <inheritdoc/>
|
||||
|
protected override void OnClickPrimary(RoutedEventArgs? e) |
||||
|
{ |
||||
|
Toggle(); |
||||
|
|
||||
|
base.OnClickPrimary(e); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,271 @@ |
|||||
|
<Styles xmlns="https://github.com/avaloniaui" |
||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
||||
|
x:CompileBindings="True" |
||||
|
xmlns:converters="using:Avalonia.Controls.Converters"> |
||||
|
|
||||
|
<!-- This style is heavily based on the Fluent v1 style. |
||||
|
The base resources are switched out along with a few minor changes such as Padding, CornerRadius. --> |
||||
|
|
||||
|
<Design.PreviewWith> |
||||
|
<Border Padding="20"> |
||||
|
<SplitButton /> |
||||
|
</Border> |
||||
|
</Design.PreviewWith> |
||||
|
|
||||
|
<Styles.Resources> |
||||
|
<x:Double x:Key="SplitButtonPrimaryButtonSize">24</x:Double> |
||||
|
<x:Double x:Key="SplitButtonSecondaryButtonSize">24</x:Double> |
||||
|
<x:Double x:Key="SplitButtonSeparatorWidth">1</x:Double> |
||||
|
<Thickness x:Key="SplitButtonBorderThemeThickness">1</Thickness> |
||||
|
|
||||
|
<converters:MarginMultiplierConverter x:Key="PrimaryButtonBorderMultiplier" Left="True" Top="True" Bottom="True" Indent="1" /> |
||||
|
<converters:MarginMultiplierConverter x:Key="SecondaryButtonBorderMultiplier" Right="True" Top="True" Bottom="True" Indent="1" /> |
||||
|
<converters:MarginMultiplierConverter x:Key="SeparatorBorderMultiplier" Top="True" Bottom="True" Indent="1" /> |
||||
|
<converters:CornerRadiusFilterConverter x:Key="TopCornerRadiusFilterConverter" Filter="TopLeft, TopRight"/> |
||||
|
<converters:CornerRadiusFilterConverter x:Key="RightCornerRadiusFilterConverter" Filter="TopRight, BottomRight"/> |
||||
|
<converters:CornerRadiusFilterConverter x:Key="BottomCornerRadiusFilterConverter" Filter="BottomLeft, BottomRight"/> |
||||
|
<converters:CornerRadiusFilterConverter x:Key="LeftCornerRadiusFilterConverter" Filter="TopLeft, BottomLeft"/> |
||||
|
|
||||
|
<SolidColorBrush x:Key="SplitButtonBackground" Color="{DynamicResource ThemeControlMidColor}" /> |
||||
|
<SolidColorBrush x:Key="SplitButtonBackgroundPointerOver" Color="{DynamicResource ThemeControlMidColor}" /> |
||||
|
<SolidColorBrush x:Key="SplitButtonBackgroundPressed" Color="{DynamicResource ThemeBorderHighColor}" /> |
||||
|
<SolidColorBrush x:Key="SplitButtonBackgroundDisabled" Color="{DynamicResource ThemeControlMidColor}" Opacity="{DynamicResource ThemeDisabledOpacity}" /> |
||||
|
<SolidColorBrush x:Key="SplitButtonBackgroundChecked" Color="{DynamicResource ThemeBorderHighColor}" /> |
||||
|
<SolidColorBrush x:Key="SplitButtonBackgroundCheckedPointerOver" Color="{DynamicResource ThemeBorderHighColor}" /> |
||||
|
<SolidColorBrush x:Key="SplitButtonBackgroundCheckedPressed" Color="{DynamicResource ThemeBorderHighColor}" /> |
||||
|
<SolidColorBrush x:Key="SplitButtonBackgroundCheckedDisabled" Color="{DynamicResource ThemeControlHighColor}" Opacity="{DynamicResource ThemeDisabledOpacity}" /> |
||||
|
|
||||
|
<SolidColorBrush x:Key="SplitButtonForeground" Color="{DynamicResource ThemeForegroundColor}" /> |
||||
|
<SolidColorBrush x:Key="SplitButtonForegroundPointerOver" Color="{DynamicResource ThemeForegroundColor}" /> |
||||
|
<SolidColorBrush x:Key="SplitButtonForegroundPressed" Color="{DynamicResource ThemeForegroundColor}" /> |
||||
|
<SolidColorBrush x:Key="SplitButtonForegroundDisabled" Color="{DynamicResource ThemeForegroundColor}" /> |
||||
|
<SolidColorBrush x:Key="SplitButtonForegroundChecked" Color="{DynamicResource ThemeForegroundColor}" /> |
||||
|
<SolidColorBrush x:Key="SplitButtonForegroundCheckedPointerOver" Color="{DynamicResource ThemeForegroundColor}" /> |
||||
|
<SolidColorBrush x:Key="SplitButtonForegroundCheckedPressed" Color="{DynamicResource ThemeForegroundColor}" /> |
||||
|
<SolidColorBrush x:Key="SplitButtonForegroundCheckedDisabled" Color="{DynamicResource ThemeForegroundColor}" /> |
||||
|
|
||||
|
<SolidColorBrush x:Key="SplitButtonBorderBrush" Color="{DynamicResource ThemeBorderLowColor}" /> |
||||
|
<SolidColorBrush x:Key="SplitButtonBorderBrushPointerOver" Color="{DynamicResource ThemeBorderMidColor}" /> |
||||
|
<SolidColorBrush x:Key="SplitButtonBorderBrushPressed" Color="{DynamicResource ThemeBorderLowColor}" /> |
||||
|
<SolidColorBrush x:Key="SplitButtonBorderBrushDisabled" Color="{DynamicResource ThemeBorderLowColor}" /> |
||||
|
<SolidColorBrush x:Key="SplitButtonBorderBrushChecked" Color="{DynamicResource ThemeBorderMidColor}" /> |
||||
|
<SolidColorBrush x:Key="SplitButtonBorderBrushCheckedPointerOver" Color="{DynamicResource ThemeBorderMidColor}" /> |
||||
|
<SolidColorBrush x:Key="SplitButtonBorderBrushCheckedPressed" Color="{DynamicResource ThemeControlHighColor}" /> |
||||
|
<SolidColorBrush x:Key="SplitButtonBorderBrushCheckedDisabled" Color="{DynamicResource ThemeControlMidColor}" Opacity="{DynamicResource ThemeDisabledOpacity}" /> |
||||
|
</Styles.Resources> |
||||
|
|
||||
|
<Style Selector="SplitButton"> |
||||
|
<Setter Property="Background" Value="{DynamicResource SplitButtonBackground}" /> |
||||
|
<Setter Property="Foreground" Value="{DynamicResource SplitButtonForeground}" /> |
||||
|
<Setter Property="BorderBrush" Value="{DynamicResource SplitButtonBorderBrush}" /> |
||||
|
<Setter Property="BorderThickness" Value="{DynamicResource SplitButtonBorderThemeThickness}" /> |
||||
|
<Setter Property="HorizontalAlignment" Value="Left" /> |
||||
|
<Setter Property="VerticalAlignment" Value="Center" /> |
||||
|
<!--<Setter Property="UseSystemFocusVisuals" Value="True" /> |
||||
|
<Setter Property="FocusVisualMargin" Value="-3" />--> |
||||
|
<Setter Property="KeyboardNavigation.IsTabStop" Value="True" /> |
||||
|
<Setter Property="Focusable" Value="True" /> |
||||
|
<Setter Property="Padding" Value="4" /> |
||||
|
<Setter Property="CornerRadius" Value="0" /> |
||||
|
<Setter Property="Template"> |
||||
|
<Setter.Value> |
||||
|
<ControlTemplate> |
||||
|
<Grid> |
||||
|
<Grid.ColumnDefinitions> |
||||
|
<ColumnDefinition Width="*" /> |
||||
|
<ColumnDefinition Width="Auto" /> |
||||
|
<ColumnDefinition Width="Auto" /> |
||||
|
</Grid.ColumnDefinitions> |
||||
|
|
||||
|
<Button x:Name="PART_PrimaryButton" |
||||
|
Grid.Column="0" |
||||
|
MinWidth="{DynamicResource SplitButtonPrimaryButtonSize}" |
||||
|
Foreground="{TemplateBinding Foreground}" |
||||
|
Background="{TemplateBinding Background}" |
||||
|
BorderThickness="{TemplateBinding BorderThickness, Converter={StaticResource PrimaryButtonBorderMultiplier}}" |
||||
|
BorderBrush="{TemplateBinding BorderBrush}" |
||||
|
Content="{TemplateBinding Content}" |
||||
|
ContentTemplate="{TemplateBinding ContentTemplate}" |
||||
|
Command="{TemplateBinding Command}" |
||||
|
CommandParameter="{TemplateBinding CommandParameter}" |
||||
|
FontFamily="{TemplateBinding FontFamily}" |
||||
|
FontSize="{TemplateBinding FontSize}" |
||||
|
FontWeight="{TemplateBinding FontWeight}" |
||||
|
HorizontalAlignment="Stretch" |
||||
|
VerticalAlignment="Stretch" |
||||
|
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" |
||||
|
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}" |
||||
|
Padding="{TemplateBinding Padding}" |
||||
|
Focusable="False" |
||||
|
KeyboardNavigation.IsTabStop="False" /> |
||||
|
|
||||
|
<Border x:Name="SeparatorBorder" |
||||
|
Grid.Column="1" |
||||
|
Background="Transparent" |
||||
|
Width="{DynamicResource SplitButtonSeparatorWidth}" |
||||
|
BorderThickness="{TemplateBinding BorderThickness, Converter={StaticResource SeparatorBorderMultiplier}}" |
||||
|
BorderBrush="{TemplateBinding BorderBrush}" /> |
||||
|
|
||||
|
<Button x:Name="PART_SecondaryButton" |
||||
|
Grid.Column="2" |
||||
|
MinWidth="{DynamicResource SplitButtonSecondaryButtonSize}" |
||||
|
BorderBrush="{TemplateBinding BorderBrush}" |
||||
|
Foreground="{TemplateBinding Foreground}" |
||||
|
Background="{TemplateBinding Background}" |
||||
|
BorderThickness="{TemplateBinding BorderThickness, Converter={StaticResource SecondaryButtonBorderMultiplier}}" |
||||
|
Padding="0" |
||||
|
HorizontalContentAlignment="Center" |
||||
|
VerticalContentAlignment="Center" |
||||
|
HorizontalAlignment="Stretch" |
||||
|
VerticalAlignment="Stretch" |
||||
|
Focusable="False" |
||||
|
KeyboardNavigation.IsTabStop="False" /> |
||||
|
</Grid> |
||||
|
</ControlTemplate> |
||||
|
</Setter.Value> |
||||
|
</Setter> |
||||
|
</Style> |
||||
|
|
||||
|
<!-- Default overridable styles --> |
||||
|
<Style Selector="SplitButton /template/ Button#PART_PrimaryButton"> |
||||
|
<Setter Property="CornerRadius" Value="{TemplateBinding CornerRadius, Converter={StaticResource LeftCornerRadiusFilterConverter}}" /> |
||||
|
</Style> |
||||
|
<Style Selector="SplitButton /template/ Button#PART_SecondaryButton"> |
||||
|
<Setter Property="CornerRadius" Value="{TemplateBinding CornerRadius, Converter={StaticResource RightCornerRadiusFilterConverter}}" /> |
||||
|
<Setter Property="Content"> |
||||
|
<Template> |
||||
|
<PathIcon Height="12" |
||||
|
Width="12" |
||||
|
Data="M1939 486L2029 576L1024 1581L19 576L109 486L1024 1401L1939 486Z" /> |
||||
|
</Template> |
||||
|
</Setter> |
||||
|
</Style> |
||||
|
|
||||
|
<!-- Primary and Secondary buttons PointerOver State --> |
||||
|
<Style Selector="SplitButton /template/ Button#PART_PrimaryButton:pointerover /template/ ContentPresenter, |
||||
|
SplitButton /template/ Button#PART_SecondaryButton:pointerover /template/ ContentPresenter"> |
||||
|
<Setter Property="Border.Background" Value="{DynamicResource SplitButtonBackgroundPointerOver}" /> |
||||
|
<Setter Property="Border.BorderBrush" Value="{DynamicResource SplitButtonBorderBrushPointerOver}" /> |
||||
|
<Setter Property="TextBlock.Foreground" Value="{DynamicResource SplitButtonForegroundPointerOver}" /> |
||||
|
</Style> |
||||
|
<Style Selector="SplitButton /template/ Button#PART_SecondaryButton:pointerover PathIcon"> |
||||
|
<Setter Property="Foreground" Value="{DynamicResource SplitButtonForegroundPointerOver}" /> |
||||
|
</Style> |
||||
|
|
||||
|
<!-- Primary and Secondary buttons Pressed State --> |
||||
|
<Style Selector="SplitButton /template/ Button#PART_PrimaryButton:pressed /template/ ContentPresenter, |
||||
|
SplitButton /template/ Button#PART_SecondaryButton:pressed /template/ ContentPresenter"> |
||||
|
<Setter Property="Border.Background" Value="{DynamicResource SplitButtonBackgroundPressed}" /> |
||||
|
<Setter Property="Border.BorderBrush" Value="{DynamicResource SplitButtonBorderBrushPressed}" /> |
||||
|
<Setter Property="TextBlock.Foreground" Value="{DynamicResource SplitButtonForegroundPressed}" /> |
||||
|
</Style> |
||||
|
<Style Selector="SplitButton /template/ Button#PART_SecondaryButton:pressed PathIcon"> |
||||
|
<Setter Property="Foreground" Value="{DynamicResource SplitButtonForegroundPressed}" /> |
||||
|
</Style> |
||||
|
|
||||
|
<!-- SplitButton Pressed State --> |
||||
|
<Style Selector="SplitButton:pressed /template/ Button#PART_PrimaryButton /template/ ContentPresenter, |
||||
|
SplitButton:pressed /template/ Button#PART_SecondaryButton /template/ ContentPresenter, |
||||
|
SplitButton:pressed /template/ Border#SeparatorBorder"> |
||||
|
<Setter Property="Border.Background" Value="{DynamicResource SplitButtonBackgroundPressed}" /> |
||||
|
<Setter Property="Border.BorderBrush" Value="{DynamicResource SplitButtonBorderBrushPressed}" /> |
||||
|
<Setter Property="TextBlock.Foreground" Value="{DynamicResource SplitButtonForegroundPressed}" /> |
||||
|
</Style> |
||||
|
<Style Selector="SplitButton:pressed /template/ Button#PART_SecondaryButton PathIcon"> |
||||
|
<Setter Property="Foreground" Value="{DynamicResource SplitButtonForegroundPressed}" /> |
||||
|
</Style> |
||||
|
|
||||
|
<!-- Primary and Secondary buttons Flyout Open State --> |
||||
|
<Style Selector="SplitButton:flyout-open /template/ Button#PART_PrimaryButton /template/ ContentPresenter, |
||||
|
SplitButton:flyout-open /template/ Button#PART_SecondaryButton /template/ ContentPresenter, |
||||
|
SplitButton:flyout-open /template/ Border#SeparatorBorder"> |
||||
|
<Setter Property="Border.Background" Value="{DynamicResource SplitButtonBackgroundPressed}" /> |
||||
|
<Setter Property="Border.BorderBrush" Value="{DynamicResource SplitButtonBorderBrushPressed}" /> |
||||
|
<Setter Property="TextBlock.Foreground" Value="{DynamicResource SplitButtonForegroundPressed}" /> |
||||
|
</Style> |
||||
|
<Style Selector="SplitButton:flyout-open /template/ Button#PART_SecondaryButton PathIcon"> |
||||
|
<Setter Property="Foreground" Value="{DynamicResource SplitButtonForegroundPressed}" /> |
||||
|
</Style> |
||||
|
|
||||
|
<!-- Disabled State --> |
||||
|
<Style Selector="SplitButton:disabled /template/ Button#PART_PrimaryButton /template/ ContentPresenter, |
||||
|
SplitButton:disabled /template/ Button#PART_SecondaryButton /template/ ContentPresenter, |
||||
|
SplitButton:disabled /template/ Border#SeparatorBorder"> |
||||
|
<Setter Property="Border.Background" Value="{DynamicResource SplitButtonBackgroundDisabled}" /> |
||||
|
<Setter Property="Border.BorderBrush" Value="{DynamicResource SplitButtonBorderBrushDisabled}" /> |
||||
|
<Setter Property="TextBlock.Foreground" Value="{DynamicResource SplitButtonForegroundDisabled}" /> |
||||
|
</Style> |
||||
|
<Style Selector="SplitButton:disabled /template/ Button#PART_SecondaryButton PathIcon"> |
||||
|
<Setter Property="Foreground" Value="{DynamicResource SplitButtonForegroundDisabled}" /> |
||||
|
</Style> |
||||
|
|
||||
|
<!-- Checked State --> |
||||
|
<Style Selector="SplitButton:checked /template/ Button#PART_PrimaryButton /template/ ContentPresenter, |
||||
|
SplitButton:checked /template/ Button#PART_SecondaryButton /template/ ContentPresenter, |
||||
|
SplitButton:checked /template/ Border#SeparatorBorder"> |
||||
|
<Setter Property="Border.Background" Value="{DynamicResource SplitButtonBackgroundChecked}" /> |
||||
|
<Setter Property="Border.BorderBrush" Value="{DynamicResource SplitButtonBorderBrushChecked}" /> |
||||
|
<Setter Property="TextBlock.Foreground" Value="{DynamicResource SplitButtonForegroundChecked}" /> |
||||
|
</Style> |
||||
|
<Style Selector="SplitButton:checked /template/ Button#PART_SecondaryButton PathIcon"> |
||||
|
<Setter Property="Foreground" Value="{DynamicResource SplitButtonForegroundChecked}" /> |
||||
|
</Style> |
||||
|
|
||||
|
<!-- Checked PointerOver State --> |
||||
|
<Style Selector="SplitButton:checked /template/ Button#PART_PrimaryButton:pointerover /template/ ContentPresenter, |
||||
|
SplitButton:checked /template/ Button#PART_SecondaryButton:pointerover /template/ ContentPresenter"> |
||||
|
<Setter Property="Border.Background" Value="{DynamicResource SplitButtonBackgroundCheckedPointerOver}" /> |
||||
|
<Setter Property="Border.BorderBrush" Value="{DynamicResource SplitButtonBorderBrushCheckedPointerOver}" /> |
||||
|
<Setter Property="TextBlock.Foreground" Value="{DynamicResource SplitButtonForegroundCheckedPointerOver}" /> |
||||
|
</Style> |
||||
|
<Style Selector="SplitButton:checked /template/ Button#PART_SecondaryButton:pointerover PathIcon"> |
||||
|
<Setter Property="Foreground" Value="{DynamicResource SplitButtonForegroundCheckedPointerOver}" /> |
||||
|
</Style> |
||||
|
|
||||
|
<!-- Checked Pressed State --> |
||||
|
<Style Selector="SplitButton:checked /template/ Button#PART_PrimaryButton:pressed /template/ ContentPresenter, |
||||
|
SplitButton:checked /template/ Button#PART_SecondaryButton:pressed /template/ ContentPresenter"> |
||||
|
<Setter Property="Border.Background" Value="{DynamicResource SplitButtonBackgroundCheckedPressed}" /> |
||||
|
<Setter Property="Border.BorderBrush" Value="{DynamicResource SplitButtonBorderBrushCheckedPressed}" /> |
||||
|
<Setter Property="TextBlock.Foreground" Value="{DynamicResource SplitButtonForegroundCheckedPressed}" /> |
||||
|
</Style> |
||||
|
<Style Selector="SplitButton:checked /template/ Button#PART_SecondaryButton:pressed PathIcon"> |
||||
|
<Setter Property="Foreground" Value="{DynamicResource SplitButtonForegroundCheckedPressed}" /> |
||||
|
</Style> |
||||
|
|
||||
|
<!-- SplitButton Checked Pressed State --> |
||||
|
<Style Selector="SplitButton:pressed:checked /template/ Button#PART_PrimaryButton /template/ ContentPresenter, |
||||
|
SplitButton:pressed:checked /template/ Button#PART_SecondaryButton /template/ ContentPresenter, |
||||
|
SplitButton:pressed:checked /template/ Border#SeparatorBorder"> |
||||
|
<Setter Property="Border.Background" Value="{DynamicResource SplitButtonBackgroundCheckedPressed}" /> |
||||
|
<Setter Property="Border.BorderBrush" Value="{DynamicResource SplitButtonBorderBrushCheckedPressed}" /> |
||||
|
<Setter Property="TextBlock.Foreground" Value="{DynamicResource SplitButtonForegroundCheckedPressed}" /> |
||||
|
</Style> |
||||
|
<Style Selector="SplitButton:pressed:checked /template/ Button#PART_SecondaryButton PathIcon"> |
||||
|
<Setter Property="Foreground" Value="{DynamicResource SplitButtonForegroundCheckedPressed}" /> |
||||
|
</Style> |
||||
|
|
||||
|
<!-- Checked Flyout Open State --> |
||||
|
<Style Selector="SplitButton:checked:flyout-open /template/ Button#PART_PrimaryButton /template/ ContentPresenter, |
||||
|
SplitButton:checked:flyout-open /template/ Button#PART_SecondaryButton /template/ ContentPresenter, |
||||
|
SplitButton:checked:flyout-open /template/ Border#SeparatorBorder"> |
||||
|
<Setter Property="Border.Background" Value="{DynamicResource SplitButtonBackgroundCheckedPressed}" /> |
||||
|
<Setter Property="Border.BorderBrush" Value="{DynamicResource SplitButtonBorderBrushCheckedPressed}" /> |
||||
|
<Setter Property="TextBlock.Foreground" Value="{DynamicResource SplitButtonForegroundCheckedPressed}" /> |
||||
|
</Style> |
||||
|
<Style Selector="SplitButton:checked:flyout-open /template/ Button#PART_SecondaryButton PathIcon"> |
||||
|
<Setter Property="Foreground" Value="{DynamicResource SplitButtonForegroundCheckedPressed}" /> |
||||
|
</Style> |
||||
|
|
||||
|
<!-- Disabled Checked State --> |
||||
|
<Style Selector="SplitButton:checked:disabled /template/ Button#PART_PrimaryButton /template/ ContentPresenter, |
||||
|
SplitButton:checked:disabled /template/ Button#PART_SecondaryButton /template/ ContentPresenter, |
||||
|
SplitButton:checked:disabled /template/ Border#SeparatorBorder"> |
||||
|
<Setter Property="Border.Background" Value="{DynamicResource SplitButtonBackgroundCheckedDisabled}" /> |
||||
|
<Setter Property="Border.BorderBrush" Value="{DynamicResource SplitButtonBorderBrushCheckedDisabled}" /> |
||||
|
<Setter Property="TextBlock.Foreground" Value="{DynamicResource SplitButtonForegroundCheckedDisabled}" /> |
||||
|
</Style> |
||||
|
<Style Selector="SplitButton:checked:disabled /template/ Button#PART_SecondaryButton PathIcon"> |
||||
|
<Setter Property="Foreground" Value="{DynamicResource SplitButtonForegroundCheckedDisabled}" /> |
||||
|
</Style> |
||||
|
</Styles> |
||||
@ -0,0 +1,247 @@ |
|||||
|
<Styles xmlns="https://github.com/avaloniaui" |
||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
||||
|
x:CompileBindings="True" |
||||
|
xmlns:converters="using:Avalonia.Controls.Converters"> |
||||
|
|
||||
|
<Design.PreviewWith> |
||||
|
<Border Padding="60"> |
||||
|
<StackPanel> |
||||
|
<SplitButton Content="Hello World"> |
||||
|
<SplitButton.Flyout> |
||||
|
<Flyout>Hello</Flyout> |
||||
|
</SplitButton.Flyout> |
||||
|
</SplitButton> |
||||
|
<ToggleSplitButton Content="Hello World"> |
||||
|
<ToggleSplitButton.Flyout> |
||||
|
<Flyout>Hello</Flyout> |
||||
|
</ToggleSplitButton.Flyout> |
||||
|
</ToggleSplitButton> |
||||
|
</StackPanel> |
||||
|
</Border> |
||||
|
</Design.PreviewWith> |
||||
|
|
||||
|
<Styles.Resources> |
||||
|
<x:Double x:Key="SplitButtonPrimaryButtonSize">32</x:Double> |
||||
|
<x:Double x:Key="SplitButtonSecondaryButtonSize">32</x:Double> |
||||
|
<x:Double x:Key="SplitButtonSeparatorWidth">1</x:Double> |
||||
|
|
||||
|
<converters:MarginMultiplierConverter x:Key="PrimaryButtonBorderMultiplier" Left="True" Top="True" Bottom="True" Indent="1" /> |
||||
|
<converters:MarginMultiplierConverter x:Key="SecondaryButtonBorderMultiplier" Right="True" Top="True" Bottom="True" Indent="1" /> |
||||
|
<converters:MarginMultiplierConverter x:Key="SeparatorBorderMultiplier" Top="True" Bottom="True" Indent="1" /> |
||||
|
</Styles.Resources> |
||||
|
|
||||
|
<Style Selector="SplitButton"> |
||||
|
<Setter Property="Background" Value="{DynamicResource SplitButtonBackground}" /> |
||||
|
<Setter Property="Foreground" Value="{DynamicResource SplitButtonForeground}" /> |
||||
|
<Setter Property="BorderBrush" Value="{DynamicResource SplitButtonBorderBrush}" /> |
||||
|
<Setter Property="BorderThickness" Value="{DynamicResource SplitButtonBorderThemeThickness}" /> |
||||
|
<Setter Property="HorizontalAlignment" Value="Left" /> |
||||
|
<Setter Property="VerticalAlignment" Value="Center" /> |
||||
|
<!--<Setter Property="UseSystemFocusVisuals" Value="True" /> |
||||
|
<Setter Property="FocusVisualMargin" Value="-3" />--> |
||||
|
<Setter Property="KeyboardNavigation.IsTabStop" Value="True" /> |
||||
|
<Setter Property="Focusable" Value="True" /> |
||||
|
<Setter Property="Padding" Value="{DynamicResource ButtonPadding}" /> |
||||
|
<Setter Property="CornerRadius" Value="{DynamicResource ControlCornerRadius}" /> |
||||
|
<Setter Property="Template"> |
||||
|
<Setter.Value> |
||||
|
<ControlTemplate> |
||||
|
<Grid> |
||||
|
<Grid.ColumnDefinitions> |
||||
|
<ColumnDefinition Width="*" /> |
||||
|
<ColumnDefinition Width="Auto" /> |
||||
|
<ColumnDefinition Width="Auto" /> |
||||
|
</Grid.ColumnDefinitions> |
||||
|
|
||||
|
<Button x:Name="PART_PrimaryButton" |
||||
|
Grid.Column="0" |
||||
|
MinWidth="{DynamicResource SplitButtonPrimaryButtonSize}" |
||||
|
Foreground="{TemplateBinding Foreground}" |
||||
|
Background="{TemplateBinding Background}" |
||||
|
BorderThickness="{TemplateBinding BorderThickness, Converter={StaticResource PrimaryButtonBorderMultiplier}}" |
||||
|
BorderBrush="{TemplateBinding BorderBrush}" |
||||
|
Content="{TemplateBinding Content}" |
||||
|
ContentTemplate="{TemplateBinding ContentTemplate}" |
||||
|
Command="{TemplateBinding Command}" |
||||
|
CommandParameter="{TemplateBinding CommandParameter}" |
||||
|
FontFamily="{TemplateBinding FontFamily}" |
||||
|
FontSize="{TemplateBinding FontSize}" |
||||
|
FontWeight="{TemplateBinding FontWeight}" |
||||
|
HorizontalAlignment="Stretch" |
||||
|
VerticalAlignment="Stretch" |
||||
|
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" |
||||
|
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}" |
||||
|
Padding="{TemplateBinding Padding}" |
||||
|
Focusable="False" |
||||
|
KeyboardNavigation.IsTabStop="False" /> |
||||
|
|
||||
|
<Border x:Name="SeparatorBorder" |
||||
|
Grid.Column="1" |
||||
|
Background="Transparent" |
||||
|
Width="{DynamicResource SplitButtonSeparatorWidth}" |
||||
|
BorderThickness="{TemplateBinding BorderThickness, Converter={StaticResource SeparatorBorderMultiplier}}" |
||||
|
BorderBrush="{TemplateBinding BorderBrush}" /> |
||||
|
|
||||
|
<Button x:Name="PART_SecondaryButton" |
||||
|
Grid.Column="2" |
||||
|
MinWidth="{DynamicResource SplitButtonSecondaryButtonSize}" |
||||
|
BorderBrush="{TemplateBinding BorderBrush}" |
||||
|
Foreground="{TemplateBinding Foreground}" |
||||
|
Background="{TemplateBinding Background}" |
||||
|
BorderThickness="{TemplateBinding BorderThickness, Converter={StaticResource SecondaryButtonBorderMultiplier}}" |
||||
|
Padding="0" |
||||
|
HorizontalContentAlignment="Center" |
||||
|
VerticalContentAlignment="Center" |
||||
|
HorizontalAlignment="Stretch" |
||||
|
VerticalAlignment="Stretch" |
||||
|
Focusable="False" |
||||
|
KeyboardNavigation.IsTabStop="False" /> |
||||
|
</Grid> |
||||
|
</ControlTemplate> |
||||
|
</Setter.Value> |
||||
|
</Setter> |
||||
|
</Style> |
||||
|
|
||||
|
<!-- Default overridable styles --> |
||||
|
<Style Selector="SplitButton /template/ Button#PART_PrimaryButton"> |
||||
|
<Setter Property="CornerRadius" Value="{TemplateBinding CornerRadius, Converter={StaticResource LeftCornerRadiusFilterConverter}}" /> |
||||
|
</Style> |
||||
|
<Style Selector="SplitButton /template/ Button#PART_SecondaryButton"> |
||||
|
<Setter Property="CornerRadius" Value="{TemplateBinding CornerRadius, Converter={StaticResource RightCornerRadiusFilterConverter}}" /> |
||||
|
<Setter Property="Content"> |
||||
|
<Template> |
||||
|
<PathIcon Height="12" |
||||
|
Width="12" |
||||
|
Data="M1939 486L2029 576L1024 1581L19 576L109 486L1024 1401L1939 486Z" /> |
||||
|
</Template> |
||||
|
</Setter> |
||||
|
</Style> |
||||
|
|
||||
|
<!-- Primary and Secondary buttons PointerOver State --> |
||||
|
<Style Selector="SplitButton /template/ Button#PART_PrimaryButton:pointerover /template/ ContentPresenter, |
||||
|
SplitButton /template/ Button#PART_SecondaryButton:pointerover /template/ ContentPresenter"> |
||||
|
<Setter Property="Border.Background" Value="{DynamicResource SplitButtonBackgroundPointerOver}" /> |
||||
|
<Setter Property="Border.BorderBrush" Value="{DynamicResource SplitButtonBorderBrushPointerOver}" /> |
||||
|
<Setter Property="TextBlock.Foreground" Value="{DynamicResource SplitButtonForegroundPointerOver}" /> |
||||
|
</Style> |
||||
|
<Style Selector="SplitButton /template/ Button#PART_SecondaryButton:pointerover PathIcon"> |
||||
|
<Setter Property="Foreground" Value="{DynamicResource SplitButtonForegroundPointerOver}" /> |
||||
|
</Style> |
||||
|
|
||||
|
<!-- Primary and Secondary buttons Pressed State --> |
||||
|
<Style Selector="SplitButton /template/ Button#PART_PrimaryButton:pressed /template/ ContentPresenter, |
||||
|
SplitButton /template/ Button#PART_SecondaryButton:pressed /template/ ContentPresenter"> |
||||
|
<Setter Property="Border.Background" Value="{DynamicResource SplitButtonBackgroundPressed}" /> |
||||
|
<Setter Property="Border.BorderBrush" Value="{DynamicResource SplitButtonBorderBrushPressed}" /> |
||||
|
<Setter Property="TextBlock.Foreground" Value="{DynamicResource SplitButtonForegroundPressed}" /> |
||||
|
</Style> |
||||
|
<Style Selector="SplitButton /template/ Button#PART_SecondaryButton:pressed PathIcon"> |
||||
|
<Setter Property="Foreground" Value="{DynamicResource SplitButtonForegroundPressed}" /> |
||||
|
</Style> |
||||
|
|
||||
|
<!-- SplitButton Pressed State --> |
||||
|
<Style Selector="SplitButton:pressed /template/ Button#PART_PrimaryButton /template/ ContentPresenter, |
||||
|
SplitButton:pressed /template/ Button#PART_SecondaryButton /template/ ContentPresenter, |
||||
|
SplitButton:pressed /template/ Border#SeparatorBorder"> |
||||
|
<Setter Property="Border.Background" Value="{DynamicResource SplitButtonBackgroundPressed}" /> |
||||
|
<Setter Property="Border.BorderBrush" Value="{DynamicResource SplitButtonBorderBrushPressed}" /> |
||||
|
<Setter Property="TextBlock.Foreground" Value="{DynamicResource SplitButtonForegroundPressed}" /> |
||||
|
</Style> |
||||
|
<Style Selector="SplitButton:pressed /template/ Button#PART_SecondaryButton PathIcon"> |
||||
|
<Setter Property="Foreground" Value="{DynamicResource SplitButtonForegroundPressed}" /> |
||||
|
</Style> |
||||
|
|
||||
|
<!-- Primary and Secondary buttons Flyout Open State --> |
||||
|
<Style Selector="SplitButton:flyout-open /template/ Button#PART_PrimaryButton /template/ ContentPresenter, |
||||
|
SplitButton:flyout-open /template/ Button#PART_SecondaryButton /template/ ContentPresenter, |
||||
|
SplitButton:flyout-open /template/ Border#SeparatorBorder"> |
||||
|
<Setter Property="Border.Background" Value="{DynamicResource SplitButtonBackgroundPressed}" /> |
||||
|
<Setter Property="Border.BorderBrush" Value="{DynamicResource SplitButtonBorderBrushPressed}" /> |
||||
|
<Setter Property="TextBlock.Foreground" Value="{DynamicResource SplitButtonForegroundPressed}" /> |
||||
|
</Style> |
||||
|
<Style Selector="SplitButton:flyout-open /template/ Button#PART_SecondaryButton PathIcon"> |
||||
|
<Setter Property="Foreground" Value="{DynamicResource SplitButtonForegroundPressed}" /> |
||||
|
</Style> |
||||
|
|
||||
|
<!-- Disabled State --> |
||||
|
<Style Selector="SplitButton:disabled /template/ Button#PART_PrimaryButton /template/ ContentPresenter, |
||||
|
SplitButton:disabled /template/ Button#PART_SecondaryButton /template/ ContentPresenter, |
||||
|
SplitButton:disabled /template/ Border#SeparatorBorder"> |
||||
|
<Setter Property="Border.Background" Value="{DynamicResource SplitButtonBackgroundDisabled}" /> |
||||
|
<Setter Property="Border.BorderBrush" Value="{DynamicResource SplitButtonBorderBrushDisabled}" /> |
||||
|
<Setter Property="TextBlock.Foreground" Value="{DynamicResource SplitButtonForegroundDisabled}" /> |
||||
|
</Style> |
||||
|
<Style Selector="SplitButton:disabled /template/ Button#PART_SecondaryButton PathIcon"> |
||||
|
<Setter Property="Foreground" Value="{DynamicResource SplitButtonForegroundDisabled}" /> |
||||
|
</Style> |
||||
|
|
||||
|
<!-- Checked State --> |
||||
|
<Style Selector="SplitButton:checked /template/ Button#PART_PrimaryButton /template/ ContentPresenter, |
||||
|
SplitButton:checked /template/ Button#PART_SecondaryButton /template/ ContentPresenter, |
||||
|
SplitButton:checked /template/ Border#SeparatorBorder"> |
||||
|
<Setter Property="Border.Background" Value="{DynamicResource SplitButtonBackgroundChecked}" /> |
||||
|
<Setter Property="Border.BorderBrush" Value="{DynamicResource SplitButtonBorderBrushChecked}" /> |
||||
|
<Setter Property="TextBlock.Foreground" Value="{DynamicResource SplitButtonForegroundChecked}" /> |
||||
|
</Style> |
||||
|
<Style Selector="SplitButton:checked /template/ Button#PART_SecondaryButton PathIcon"> |
||||
|
<Setter Property="Foreground" Value="{DynamicResource SplitButtonForegroundChecked}" /> |
||||
|
</Style> |
||||
|
|
||||
|
<!-- Checked PointerOver State --> |
||||
|
<Style Selector="SplitButton:checked /template/ Button#PART_PrimaryButton:pointerover /template/ ContentPresenter, |
||||
|
SplitButton:checked /template/ Button#PART_SecondaryButton:pointerover /template/ ContentPresenter"> |
||||
|
<Setter Property="Border.Background" Value="{DynamicResource SplitButtonBackgroundCheckedPointerOver}" /> |
||||
|
<Setter Property="Border.BorderBrush" Value="{DynamicResource SplitButtonBorderBrushCheckedPointerOver}" /> |
||||
|
<Setter Property="TextBlock.Foreground" Value="{DynamicResource SplitButtonForegroundCheckedPointerOver}" /> |
||||
|
</Style> |
||||
|
<Style Selector="SplitButton:checked /template/ Button#PART_SecondaryButton:pointerover PathIcon"> |
||||
|
<Setter Property="Foreground" Value="{DynamicResource SplitButtonForegroundCheckedPointerOver}" /> |
||||
|
</Style> |
||||
|
|
||||
|
<!-- Checked Pressed State --> |
||||
|
<Style Selector="SplitButton:checked /template/ Button#PART_PrimaryButton:pressed /template/ ContentPresenter, |
||||
|
SplitButton:checked /template/ Button#PART_SecondaryButton:pressed /template/ ContentPresenter"> |
||||
|
<Setter Property="Border.Background" Value="{DynamicResource SplitButtonBackgroundCheckedPressed}" /> |
||||
|
<Setter Property="Border.BorderBrush" Value="{DynamicResource SplitButtonBorderBrushCheckedPressed}" /> |
||||
|
<Setter Property="TextBlock.Foreground" Value="{DynamicResource SplitButtonForegroundCheckedPressed}" /> |
||||
|
</Style> |
||||
|
<Style Selector="SplitButton:checked /template/ Button#PART_SecondaryButton:pressed PathIcon"> |
||||
|
<Setter Property="Foreground" Value="{DynamicResource SplitButtonForegroundCheckedPressed}" /> |
||||
|
</Style> |
||||
|
|
||||
|
<!-- SplitButton Checked Pressed State --> |
||||
|
<Style Selector="SplitButton:pressed:checked /template/ Button#PART_PrimaryButton /template/ ContentPresenter, |
||||
|
SplitButton:pressed:checked /template/ Button#PART_SecondaryButton /template/ ContentPresenter, |
||||
|
SplitButton:pressed:checked /template/ Border#SeparatorBorder"> |
||||
|
<Setter Property="Border.Background" Value="{DynamicResource SplitButtonBackgroundCheckedPressed}" /> |
||||
|
<Setter Property="Border.BorderBrush" Value="{DynamicResource SplitButtonBorderBrushCheckedPressed}" /> |
||||
|
<Setter Property="TextBlock.Foreground" Value="{DynamicResource SplitButtonForegroundCheckedPressed}" /> |
||||
|
</Style> |
||||
|
<Style Selector="SplitButton:pressed:checked /template/ Button#PART_SecondaryButton PathIcon"> |
||||
|
<Setter Property="Foreground" Value="{DynamicResource SplitButtonForegroundCheckedPressed}" /> |
||||
|
</Style> |
||||
|
|
||||
|
<!-- Checked Flyout Open State --> |
||||
|
<Style Selector="SplitButton:checked:flyout-open /template/ Button#PART_PrimaryButton /template/ ContentPresenter, |
||||
|
SplitButton:checked:flyout-open /template/ Button#PART_SecondaryButton /template/ ContentPresenter, |
||||
|
SplitButton:checked:flyout-open /template/ Border#SeparatorBorder"> |
||||
|
<Setter Property="Border.Background" Value="{DynamicResource SplitButtonBackgroundCheckedPressed}" /> |
||||
|
<Setter Property="Border.BorderBrush" Value="{DynamicResource SplitButtonBorderBrushCheckedPressed}" /> |
||||
|
<Setter Property="TextBlock.Foreground" Value="{DynamicResource SplitButtonForegroundCheckedPressed}" /> |
||||
|
</Style> |
||||
|
<Style Selector="SplitButton:checked:flyout-open /template/ Button#PART_SecondaryButton PathIcon"> |
||||
|
<Setter Property="Foreground" Value="{DynamicResource SplitButtonForegroundCheckedPressed}" /> |
||||
|
</Style> |
||||
|
|
||||
|
<!-- Disabled Checked State --> |
||||
|
<Style Selector="SplitButton:checked:disabled /template/ Button#PART_PrimaryButton /template/ ContentPresenter, |
||||
|
SplitButton:checked:disabled /template/ Button#PART_SecondaryButton /template/ ContentPresenter, |
||||
|
SplitButton:checked:disabled /template/ Border#SeparatorBorder"> |
||||
|
<Setter Property="Border.Background" Value="{DynamicResource SplitButtonBackgroundCheckedDisabled}" /> |
||||
|
<Setter Property="Border.BorderBrush" Value="{DynamicResource SplitButtonBorderBrushCheckedDisabled}" /> |
||||
|
<Setter Property="TextBlock.Foreground" Value="{DynamicResource SplitButtonForegroundCheckedDisabled}" /> |
||||
|
</Style> |
||||
|
<Style Selector="SplitButton:checked:disabled /template/ Button#PART_SecondaryButton PathIcon"> |
||||
|
<Setter Property="Foreground" Value="{DynamicResource SplitButtonForegroundCheckedDisabled}" /> |
||||
|
</Style> |
||||
|
</Styles> |
||||
Loading…
Reference in new issue