feat: add toggle registration.

This commit is contained in:
rabbitism
2024-02-14 01:25:21 +08:00
parent f2073f4eb3
commit f67a5a313c
3 changed files with 93 additions and 27 deletions

View File

@@ -2,34 +2,50 @@
x:Class="Ursa.Demo.Pages.NavMenuDemo" x:Class="Ursa.Demo.Pages.NavMenuDemo"
xmlns="https://github.com/avaloniaui" xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:converters="clr-namespace:Ursa.Demo.Converters"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:u="https://irihi.tech/ursa" xmlns:u="https://irihi.tech/ursa"
xmlns:vm="using:Ursa.Demo.ViewModels" xmlns:vm="using:Ursa.Demo.ViewModels"
xmlns:converters="clr-namespace:Ursa.Demo.Converters"
d:DesignHeight="450" d:DesignHeight="450"
d:DesignWidth="800" d:DesignWidth="800"
x:CompileBindings="True" x:CompileBindings="True"
x:DataType="vm:NavMenuDemoViewModel" x:DataType="vm:NavMenuDemoViewModel"
mc:Ignorable="d"> mc:Ignorable="d">
<UserControl.Resources> <UserControl.Resources>
<converters:IconNameToPathConverter x:Key="IconConverter"/> <converters:IconNameToPathConverter x:Key="IconConverter" />
</UserControl.Resources> </UserControl.Resources>
<Grid ColumnDefinitions="Auto, Auto" RowDefinitions="Auto, Auto, *" HorizontalAlignment="Left"> <Grid
<ToggleButton Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" Name="collapse">Collapse</ToggleButton> HorizontalAlignment="Left"
<TextBlock Grid.Row="1" Grid.Column="0" Text="{ReflectionBinding #menu.SelectedItem.Header}" /> ColumnDefinitions="Auto, Auto"
<Border Grid.Row="2" Grid.Column="0" Theme="{DynamicResource CardBorder}" HorizontalAlignment="Left" Padding="0"> RowDefinitions="Auto, Auto, *">
<ToggleButton
Name="collapse"
Grid.Row="0"
Grid.Column="0"
Grid.ColumnSpan="2">
Collapse
</ToggleButton>
<TextBlock
Grid.Row="1"
Grid.Column="0"
Text="{ReflectionBinding #menu.SelectedItem.Header}" />
<Border
Grid.Row="2"
Grid.Column="0"
Padding="0"
HorizontalAlignment="Left"
Theme="{DynamicResource CardBorder}">
<u:NavMenu <u:NavMenu
Name="menu" Name="menu"
Header="Welcome to Ursa!"
HeaderBinding="{Binding Header}" HeaderBinding="{Binding Header}"
IconBinding="{Binding IconIndex}" IconBinding="{Binding IconIndex}"
IsHorizontalCollapsed="{Binding #collapse.IsChecked, Mode=OneWay}" IsHorizontalCollapsed="{Binding #collapse.IsChecked, Mode=OneWay}"
ItemsSource="{Binding MenuItems}" ItemsSource="{Binding MenuItems}"
SubMenuBinding="{Binding Children}"> SubMenuBinding="{Binding Children}">
<u:NavMenu.Styles> <u:NavMenu.Styles>
<Style Selector="u|NavMenuItem" x:DataType="vm:MenuItem"> <Style x:DataType="vm:MenuItem" Selector="u|NavMenuItem">
<Setter Property="IsSeparator" Value="{Binding IsSeparator}"></Setter> <Setter Property="IsSeparator" Value="{Binding IsSeparator}" />
</Style> </Style>
</u:NavMenu.Styles> </u:NavMenu.Styles>
<u:NavMenu.IconTemplate> <u:NavMenu.IconTemplate>
@@ -37,26 +53,43 @@
<u:TwoTonePathIcon <u:TwoTonePathIcon
Width="16" Width="16"
Height="16" Height="16"
Data="{Binding Converter={StaticResource IconConverter}}"
StrokeBrush="{DynamicResource SemiGrey5}"
Foreground="{DynamicResource SemiGrey5}"
ActiveStrokeBrush="{DynamicResource SemiBlue5}"
ActiveForeground="{DynamicResource SemiBlue5}" ActiveForeground="{DynamicResource SemiBlue5}"
IsActive="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=u:NavMenuItem}, Path=IsHighlighted, Mode=TwoWay}"> ActiveStrokeBrush="{DynamicResource SemiBlue5}"
</u:TwoTonePathIcon> Data="{Binding Converter={StaticResource IconConverter}}"
Foreground="{DynamicResource SemiGrey5}"
IsActive="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=u:NavMenuItem}, Path=IsHighlighted, Mode=TwoWay}"
StrokeBrush="{DynamicResource SemiGrey5}" />
</DataTemplate> </DataTemplate>
</u:NavMenu.IconTemplate> </u:NavMenu.IconTemplate>
<u:NavMenu.Footer> <u:NavMenu.Header>
<Image <Grid ColumnDefinitions="Auto, Auto" HorizontalAlignment="Center">
Width="48" <Image
Height="48" u:NavMenu.CanToggle="True"
RenderOptions.BitmapInterpolationMode="HighQuality" Width="48"
Source="../Assets/Ursa.ico" /> Height="48"
</u:NavMenu.Footer> Margin="4 12"
RenderOptions.BitmapInterpolationMode="HighQuality"
Source="../Assets/Ursa.ico" />
<TextBlock
Grid.Column="1"
Classes="H5"
VerticalAlignment="Center"
Text="Ursa Avalonia"
IsVisible="{Binding !#menu.IsHorizontalCollapsed}"
Theme="{DynamicResource TitleTextBlock}" />
</Grid>
</u:NavMenu.Header>
</u:NavMenu> </u:NavMenu>
</Border> </Border>
<TextBlock Grid.Row="1" Grid.Column="1" Text="{ReflectionBinding #menu2.SelectedItem.Header}"></TextBlock> <TextBlock
<u:NavMenu Grid.Row="2" Grid.Column="1" Name="menu2" IsHorizontalCollapsed="{Binding #collapse.IsChecked}"> Grid.Row="1"
Grid.Column="1"
Text="{ReflectionBinding #menu2.SelectedItem.Header}" />
<u:NavMenu
Name="menu2"
Grid.Row="2"
Grid.Column="1"
IsHorizontalCollapsed="{Binding #collapse.IsChecked}">
<u:NavMenuItem Header="Menu 1"> <u:NavMenuItem Header="Menu 1">
<u:NavMenuItem.Icon> <u:NavMenuItem.Icon>
<Rectangle <Rectangle
@@ -64,9 +97,9 @@
Height="10" Height="10"
Fill="Red" /> Fill="Red" />
</u:NavMenuItem.Icon> </u:NavMenuItem.Icon>
<u:NavMenuItem Header="Sub Menu 1"></u:NavMenuItem> <u:NavMenuItem Header="Sub Menu 1" />
<u:NavMenuItem Header="Sub Menu 2"></u:NavMenuItem> <u:NavMenuItem Header="Sub Menu 2" />
<u:NavMenuItem Header="Sub Menu 3"></u:NavMenuItem> <u:NavMenuItem Header="Sub Menu 3" />
</u:NavMenuItem> </u:NavMenuItem>
<u:NavMenuItem Header="Menu 2"> <u:NavMenuItem Header="Menu 2">
<u:NavMenuItem.Icon> <u:NavMenuItem.Icon>

View File

@@ -128,6 +128,9 @@
<Setter Property="Template" Value="{StaticResource DefaultNavMenuItemTemplate}" /> <Setter Property="Template" Value="{StaticResource DefaultNavMenuItemTemplate}" />
<Style Selector="^:selected"> <Style Selector="^:selected">
<Setter Property="Background" Value="{DynamicResource NavigationMenuItemSelectedBackground}" /> <Setter Property="Background" Value="{DynamicResource NavigationMenuItemSelectedBackground}" />
<Style Selector="^:pointerover">
<Setter Property="Background" Value="{DynamicResource NavigationMenuItemSelectedBackground}" />
</Style>
</Style> </Style>
<Style Selector="^:vertical-collapsed /template/ ItemsPresenter#PART_ItemsPresenter"> <Style Selector="^:vertical-collapsed /template/ ItemsPresenter#PART_ItemsPresenter">
<Setter Property="Height" Value="0" /> <Setter Property="Height" Value="0" />

View File

@@ -5,6 +5,8 @@ using Avalonia.Controls.Metadata;
using Avalonia.Controls.Primitives; using Avalonia.Controls.Primitives;
using Avalonia.Controls.Templates; using Avalonia.Controls.Templates;
using Avalonia.Data; using Avalonia.Data;
using Avalonia.Input;
using Avalonia.Interactivity;
using Avalonia.LogicalTree; using Avalonia.LogicalTree;
using Avalonia.Metadata; using Avalonia.Metadata;
using Irihi.Avalonia.Shared.Helpers; using Irihi.Avalonia.Shared.Helpers;
@@ -125,11 +127,39 @@ public class NavMenu: ItemsControl
get => GetValue(FooterProperty); get => GetValue(FooterProperty);
set => SetValue(FooterProperty, value); set => SetValue(FooterProperty, value);
} }
public static readonly AttachedProperty<bool> CanToggleProperty =
AvaloniaProperty.RegisterAttached<NavMenu, InputElement, bool>("CanToggle");
public static void SetCanToggle(InputElement obj, bool value) => obj.SetValue(CanToggleProperty, value);
public static bool GetCanToggle(InputElement obj) => obj.GetValue(CanToggleProperty);
static NavMenu() static NavMenu()
{ {
SelectedItemProperty.Changed.AddClassHandler<NavMenu, object?>((o, e) => o.OnSelectedItemChange(e)); SelectedItemProperty.Changed.AddClassHandler<NavMenu, object?>((o, e) => o.OnSelectedItemChange(e));
PropertyToPseudoClassMixin.Attach<NavMenu>(IsHorizontalCollapsedProperty, PC_HorizontalCollapsed); PropertyToPseudoClassMixin.Attach<NavMenu>(IsHorizontalCollapsedProperty, PC_HorizontalCollapsed);
CanToggleProperty.Changed.AddClassHandler<InputElement, bool>(OnInputRegisteredAsToggle);
}
private static void OnInputRegisteredAsToggle(InputElement input, AvaloniaPropertyChangedEventArgs<bool> e)
{
if (e.NewValue.Value)
{
input.AddHandler(PointerPressedEvent, OnElementToggle);
}
else
{
input.RemoveHandler(PointerPressedEvent, OnElementToggle);
}
}
private static void OnElementToggle(object? sender, RoutedEventArgs args)
{
if (sender is not InputElement input) return;
var nav = input.FindLogicalAncestorOfType<NavMenu>();
if(nav is null) return;
bool collapsed = nav.IsHorizontalCollapsed;
nav.IsHorizontalCollapsed = !collapsed;
} }
private void OnSelectedItemChange(AvaloniaPropertyChangedEventArgs<object?> args) private void OnSelectedItemChange(AvaloniaPropertyChangedEventArgs<object?> args)