* Added CommandBar * Added ContentPage * Added NavigationPage * Added TabbedPage * Added DrawerPage * More showcases * More tests * Added Connected Animations * More samples * More fixes * More fixes * Updated samples * More fixes * Fix build errors * More fixes * More changes * More changes * More fixes * Added benchmarks * Updated SwipeGestureRecognizer * Fixes based on PR feedback * More fixes * Removed Appearing/Disappearing events * Fix merge issue * More changes * Fix build * Remove TabbedPage brush properties * New showcase sample * More changes * Moved navigation brushes properties to resources * Fix default connected animation duration fallback * CommandBar returns empty list with null * Ignore AVP1030 on PrimaryCommands/SecondaryCommands for now * Updated samples * More changes and tests * Updated samples * Updated render tests * Updated tests * Added Page AutomationPeers --------- Co-authored-by: Julien Lebosquain <julien@lebosquain.net>pull/20817/head
|
After Width: | Height: | Size: 264 KiB |
|
After Width: | Height: | Size: 334 KiB |
|
After Width: | Height: | Size: 383 KiB |
|
After Width: | Height: | Size: 305 KiB |
|
After Width: | Height: | Size: 307 KiB |
|
After Width: | Height: | Size: 197 KiB |
|
After Width: | Height: | Size: 198 KiB |
|
After Width: | Height: | Size: 214 KiB |
|
After Width: | Height: | Size: 22 KiB |
|
After Width: | Height: | Size: 39 KiB |
|
After Width: | Height: | Size: 56 KiB |
|
After Width: | Height: | Size: 26 KiB |
|
After Width: | Height: | Size: 77 KiB |
|
After Width: | Height: | Size: 102 KiB |
|
After Width: | Height: | Size: 38 KiB |
|
After Width: | Height: | Size: 35 KiB |
|
After Width: | Height: | Size: 37 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 23 KiB |
|
After Width: | Height: | Size: 32 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 9.0 KiB |
|
After Width: | Height: | Size: 375 KiB |
|
After Width: | Height: | Size: 375 KiB |
|
After Width: | Height: | Size: 238 KiB |
|
After Width: | Height: | Size: 357 KiB |
|
After Width: | Height: | Size: 378 KiB |
|
After Width: | Height: | Size: 357 KiB |
|
After Width: | Height: | Size: 315 KiB |
|
After Width: | Height: | Size: 189 KiB |
|
After Width: | Height: | Size: 270 KiB |
|
After Width: | Height: | Size: 330 KiB |
|
After Width: | Height: | Size: 347 KiB |
|
After Width: | Height: | Size: 352 KiB |
|
After Width: | Height: | Size: 354 KiB |
|
After Width: | Height: | Size: 321 KiB |
|
After Width: | Height: | Size: 215 KiB |
|
After Width: | Height: | Size: 340 KiB |
|
After Width: | Height: | Size: 342 KiB |
|
After Width: | Height: | Size: 311 KiB |
|
After Width: | Height: | Size: 253 KiB |
|
After Width: | Height: | Size: 341 KiB |
|
After Width: | Height: | Size: 229 KiB |
|
After Width: | Height: | Size: 293 KiB |
|
After Width: | Height: | Size: 370 KiB |
|
After Width: | Height: | Size: 326 KiB |
|
After Width: | Height: | Size: 349 KiB |
|
After Width: | Height: | Size: 62 KiB |
|
After Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 55 KiB |
|
After Width: | Height: | Size: 45 KiB |
|
After Width: | Height: | Size: 67 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 346 KiB |
|
After Width: | Height: | Size: 458 KiB |
|
After Width: | Height: | Size: 416 KiB |
|
After Width: | Height: | Size: 216 KiB |
|
After Width: | Height: | Size: 296 KiB |
|
After Width: | Height: | Size: 389 KiB |
|
After Width: | Height: | Size: 311 KiB |
|
After Width: | Height: | Size: 338 KiB |
@ -0,0 +1,120 @@ |
|||
<UserControl xmlns="https://github.com/avaloniaui" |
|||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
|||
x:Class="ControlCatalog.Pages.CommandBarCustomizationPage"> |
|||
<UserControl.Resources> |
|||
<StreamGeometry x:Key="AddIcon">M19,13H13V19H11V13H5V11H11V5H13V11H19V13Z</StreamGeometry> |
|||
<StreamGeometry x:Key="SaveIcon">M15,9H5V5H15M12,19A3,3 0 0,1 9,16A3,3 0 0,1 12,13A3,3 0 0,1 15,16A3,3 0 0,1 12,19M17,3H5C3.89,3 3,3.9 3,5V19A2,2 0 0,0 5,21H19A2,2 0 0,0 21,19V7L17,3Z</StreamGeometry> |
|||
<StreamGeometry x:Key="ShareIcon">M18,16.08C17.24,16.08 16.56,16.38 16.04,16.85L8.91,12.7C8.96,12.47 9,12.24 9,12C9,11.76 8.96,11.53 8.91,11.3L15.96,7.19C16.5,7.69 17.21,8 18,8A3,3 0 0,0 21,5A3,3 0 0,0 18,2A3,3 0 0,0 15,5C15,5.24 15.04,5.47 15.09,5.7L8.04,9.81C7.5,9.31 6.79,9 6,9A3,3 0 0,0 3,12A3,3 0 0,0 6,15C6.79,15 7.5,14.69 8.04,14.19L15.16,18.34C15.11,18.55 15.08,18.77 15.08,19C15.08,20.61 16.39,21.91 18,21.91C19.61,21.91 20.92,20.61 20.92,19C20.92,17.39 19.61,16.08 18,16.08Z</StreamGeometry> |
|||
</UserControl.Resources> |
|||
|
|||
<DockPanel> |
|||
<ScrollViewer DockPanel.Dock="Right" Width="260"> |
|||
<StackPanel Margin="12" Spacing="8"> |
|||
<TextBlock Text="Configuration" FontWeight="SemiBold" FontSize="16" |
|||
Foreground="{DynamicResource SystemControlHighlightAccentBrush}" /> |
|||
<TextBlock Text="Live Preview" FontWeight="SemiBold" FontSize="13" /> |
|||
<CommandBar x:Name="LiveBar"> |
|||
<CommandBar.PrimaryCommands> |
|||
<AppBarButton Label="New"><AppBarButton.Icon><PathIcon Data="{StaticResource AddIcon}" /></AppBarButton.Icon></AppBarButton> |
|||
<AppBarButton Label="Save"><AppBarButton.Icon><PathIcon Data="{StaticResource SaveIcon}" /></AppBarButton.Icon></AppBarButton> |
|||
<AppBarButton Label="Share"><AppBarButton.Icon><PathIcon Data="{StaticResource ShareIcon}" /></AppBarButton.Icon></AppBarButton> |
|||
</CommandBar.PrimaryCommands> |
|||
</CommandBar> |
|||
|
|||
<Separator /> |
|||
|
|||
<TextBlock Text="Background Preset" /> |
|||
<ComboBox x:Name="BgPresetCombo" |
|||
SelectedIndex="0" |
|||
HorizontalAlignment="Stretch" |
|||
SelectionChanged="OnBgPresetChanged"> |
|||
<ComboBoxItem Content="Default" /> |
|||
<ComboBoxItem Content="Blue (#0078D4)" /> |
|||
<ComboBoxItem Content="Dark (#1C1C1E)" /> |
|||
<ComboBoxItem Content="Gradient" /> |
|||
<ComboBoxItem Content="Transparent" /> |
|||
</ComboBox> |
|||
|
|||
<TextBlock Text="Foreground" /> |
|||
<ComboBox x:Name="FgCombo" |
|||
SelectedIndex="0" |
|||
HorizontalAlignment="Stretch" |
|||
SelectionChanged="OnFgChanged"> |
|||
<ComboBoxItem Content="Default" /> |
|||
<ComboBoxItem Content="White" /> |
|||
<ComboBoxItem Content="Black" /> |
|||
</ComboBox> |
|||
|
|||
<TextBlock Text="Corner Radius" /> |
|||
<Slider x:Name="RadiusSlider" |
|||
Minimum="0" |
|||
Maximum="24" |
|||
Value="0" |
|||
ValueChanged="OnRadiusChanged" /> |
|||
<TextBlock x:Name="RadiusLabel" |
|||
Text="0" |
|||
HorizontalAlignment="Center" |
|||
Opacity="0.7" /> |
|||
|
|||
<TextBlock Text="Border Thickness" /> |
|||
<Slider x:Name="BorderSlider" |
|||
Minimum="0" |
|||
Maximum="4" |
|||
Value="0" |
|||
TickFrequency="1" |
|||
IsSnapToTickEnabled="True" |
|||
ValueChanged="OnBorderChanged" /> |
|||
<TextBlock x:Name="BorderLabel" |
|||
Text="0" |
|||
HorizontalAlignment="Center" |
|||
Opacity="0.7" /> |
|||
|
|||
<Separator /> |
|||
|
|||
<TextBlock Text="About" FontWeight="SemiBold" /> |
|||
<TextBlock Text="CommandBar inherits from TemplatedControl, so Background, Foreground, BorderBrush, BorderThickness, and CornerRadius are available out of the box." |
|||
FontSize="12" Opacity="0.7" TextWrapping="Wrap" /> |
|||
<TextBlock Text="Foreground is an inherited property: setting it on the CommandBar cascades to all PathIcons inside AppBarButton/AppBarToggleButton." |
|||
FontSize="12" Opacity="0.7" TextWrapping="Wrap" Margin="0,4,0,0" /> |
|||
</StackPanel> |
|||
</ScrollViewer> |
|||
|
|||
<Border DockPanel.Dock="Right" Width="1" Background="{DynamicResource SystemControlForegroundBaseMediumLowBrush}" /> |
|||
|
|||
<ScrollViewer> |
|||
<StackPanel Spacing="16" Margin="12,12,12,0"> |
|||
<TextBlock Classes="h2">Customize the CommandBar appearance using Background, Foreground, BorderBrush, and CornerRadius.</TextBlock> |
|||
|
|||
<TextBlock Text="Style Presets" FontWeight="SemiBold" /> |
|||
|
|||
<TextBlock Text="Default theme" FontSize="12" Opacity="0.7" /> |
|||
<CommandBar OverflowButtonVisibility="Collapsed"> |
|||
<AppBarButton Label="New"><AppBarButton.Icon><PathIcon Data="{StaticResource AddIcon}" /></AppBarButton.Icon></AppBarButton> |
|||
<AppBarButton Label="Save"><AppBarButton.Icon><PathIcon Data="{StaticResource SaveIcon}" /></AppBarButton.Icon></AppBarButton> |
|||
</CommandBar> |
|||
|
|||
<TextBlock Text="Solid color" FontSize="12" Opacity="0.7" /> |
|||
<CommandBar Background="#0078D4" Foreground="White" OverflowButtonVisibility="Collapsed"> |
|||
<AppBarButton Label="New"><AppBarButton.Icon><PathIcon Data="{StaticResource AddIcon}" /></AppBarButton.Icon></AppBarButton> |
|||
<AppBarButton Label="Save"><AppBarButton.Icon><PathIcon Data="{StaticResource SaveIcon}" /></AppBarButton.Icon></AppBarButton> |
|||
</CommandBar> |
|||
|
|||
<TextBlock Text="Dark" FontSize="12" Opacity="0.7" /> |
|||
<CommandBar Background="#1C1C1E" Foreground="White" OverflowButtonVisibility="Collapsed"> |
|||
<AppBarButton Label="New"><AppBarButton.Icon><PathIcon Data="{StaticResource AddIcon}" /></AppBarButton.Icon></AppBarButton> |
|||
<AppBarButton Label="Save"><AppBarButton.Icon><PathIcon Data="{StaticResource SaveIcon}" /></AppBarButton.Icon></AppBarButton> |
|||
</CommandBar> |
|||
|
|||
<TextBlock Text="Pill shape (CornerRadius=20)" FontSize="12" Opacity="0.7" /> |
|||
<CommandBar Background="#F0F0F0" |
|||
CornerRadius="20" |
|||
BorderBrush="#CCCCCC" |
|||
BorderThickness="1" |
|||
OverflowButtonVisibility="Collapsed"> |
|||
<AppBarButton Label="New"><AppBarButton.Icon><PathIcon Data="{StaticResource AddIcon}" /></AppBarButton.Icon></AppBarButton> |
|||
<AppBarButton Label="Save"><AppBarButton.Icon><PathIcon Data="{StaticResource SaveIcon}" /></AppBarButton.Icon></AppBarButton> |
|||
</CommandBar> |
|||
</StackPanel> |
|||
</ScrollViewer> |
|||
</DockPanel> |
|||
</UserControl> |
|||
@ -0,0 +1,90 @@ |
|||
using Avalonia.Controls; |
|||
using Avalonia.Media; |
|||
|
|||
namespace ControlCatalog.Pages |
|||
{ |
|||
public partial class CommandBarCustomizationPage : UserControl |
|||
{ |
|||
public CommandBarCustomizationPage() |
|||
{ |
|||
InitializeComponent(); |
|||
} |
|||
|
|||
private void OnBgPresetChanged(object? sender, SelectionChangedEventArgs e) |
|||
{ |
|||
if (LiveBar == null) |
|||
return; |
|||
|
|||
switch (BgPresetCombo.SelectedIndex) |
|||
{ |
|||
case 1: |
|||
LiveBar.Background = new SolidColorBrush(Color.Parse("#0078D4")); |
|||
break; |
|||
case 2: |
|||
LiveBar.Background = new SolidColorBrush(Color.Parse("#1C1C1E")); |
|||
break; |
|||
case 3: |
|||
LiveBar.Background = new LinearGradientBrush |
|||
{ |
|||
StartPoint = new Avalonia.RelativePoint(0, 0, Avalonia.RelativeUnit.Relative), |
|||
EndPoint = new Avalonia.RelativePoint(1, 0, Avalonia.RelativeUnit.Relative), |
|||
GradientStops = |
|||
{ |
|||
new GradientStop(Color.Parse("#3F51B5"), 0), |
|||
new GradientStop(Color.Parse("#E91E63"), 1) |
|||
} |
|||
}; |
|||
break; |
|||
case 4: |
|||
LiveBar.Background = Brushes.Transparent; |
|||
break; |
|||
default: |
|||
LiveBar.ClearValue(BackgroundProperty); |
|||
break; |
|||
} |
|||
} |
|||
|
|||
private void OnFgChanged(object? sender, SelectionChangedEventArgs e) |
|||
{ |
|||
if (LiveBar == null) |
|||
return; |
|||
|
|||
switch (FgCombo.SelectedIndex) |
|||
{ |
|||
case 1: |
|||
LiveBar.Foreground = Brushes.White; |
|||
break; |
|||
case 2: |
|||
LiveBar.Foreground = Brushes.Black; |
|||
break; |
|||
default: |
|||
LiveBar.ClearValue(ForegroundProperty); |
|||
break; |
|||
} |
|||
} |
|||
|
|||
private void OnRadiusChanged(object? sender, Avalonia.Controls.Primitives.RangeBaseValueChangedEventArgs e) |
|||
{ |
|||
if (LiveBar == null) |
|||
return; |
|||
|
|||
var r = (int)RadiusSlider.Value; |
|||
LiveBar.CornerRadius = new Avalonia.CornerRadius(r); |
|||
RadiusLabel.Text = $"{r}"; |
|||
} |
|||
|
|||
private void OnBorderChanged(object? sender, Avalonia.Controls.Primitives.RangeBaseValueChangedEventArgs e) |
|||
{ |
|||
if (LiveBar == null) |
|||
return; |
|||
|
|||
var t = (int)BorderSlider.Value; |
|||
LiveBar.BorderThickness = new Avalonia.Thickness(t); |
|||
BorderLabel.Text = $"{t}"; |
|||
if (t > 0) |
|||
LiveBar.BorderBrush = Brushes.Gray; |
|||
else |
|||
LiveBar.BorderBrush = null; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,75 @@ |
|||
<UserControl xmlns="https://github.com/avaloniaui" |
|||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
|||
x:Class="ControlCatalog.Pages.CommandBarDynamicOverflowPage"> |
|||
<UserControl.Resources> |
|||
<StreamGeometry x:Key="AddIcon">M19,13H13V19H11V13H5V11H11V5H13V11H19V13Z</StreamGeometry> |
|||
<StreamGeometry x:Key="SaveIcon">M15,9H5V5H15M12,19A3,3 0 0,1 9,16A3,3 0 0,1 12,13A3,3 0 0,1 15,16A3,3 0 0,1 12,19M17,3H5C3.89,3 3,3.9 3,5V19A2,2 0 0,0 5,21H19A2,2 0 0,0 21,19V7L17,3Z</StreamGeometry> |
|||
<StreamGeometry x:Key="ShareIcon">M18,16.08C17.24,16.08 16.56,16.38 16.04,16.85L8.91,12.7C8.96,12.47 9,12.24 9,12C9,11.76 8.96,11.53 8.91,11.3L15.96,7.19C16.5,7.69 17.21,8 18,8A3,3 0 0,0 21,5A3,3 0 0,0 18,2A3,3 0 0,0 15,5C15,5.24 15.04,5.47 15.09,5.7L8.04,9.81C7.5,9.31 6.79,9 6,9A3,3 0 0,0 3,12A3,3 0 0,0 6,15C6.79,15 7.5,14.69 8.04,14.19L15.16,18.34C15.11,18.55 15.08,18.77 15.08,19C15.08,20.61 16.39,21.91 18,21.91C19.61,21.91 20.92,20.61 20.92,19C20.92,17.39 19.61,16.08 18,16.08Z</StreamGeometry> |
|||
<StreamGeometry x:Key="BoldIcon">M15.6,10.79C17.04,10.07 18,8.64 18,7C18,4.79 16.21,3 14,3H7V21H14.73C16.78,21 18.5,19.37 18.5,17.32C18.5,15.82 17.72,14.53 16.5,13.77C16.2,13.59 15.9,13.44 15.6,13.32V10.79M10,6.5H13C13.83,6.5 14.5,7.17 14.5,8C14.5,8.83 13.83,9.5 13,9.5H10V6.5M13.5,17.5H10V14H13.5C14.33,14 15,14.67 15,15.5C15,16.33 14.33,17.5 13.5,17.5Z</StreamGeometry> |
|||
<StreamGeometry x:Key="ItalicIcon">M10,4V7H12.21L8.79,15H6V18H14V15H11.79L15.21,7H18V4H10Z</StreamGeometry> |
|||
<StreamGeometry x:Key="DeleteIcon">M19,4H15.5L14.5,3H9.5L8.5,4H5V6H19M6,19A2,2 0 0,0 8,21H16A2,2 0 0,0 18,19V7H6V19Z</StreamGeometry> |
|||
</UserControl.Resources> |
|||
|
|||
<DockPanel> |
|||
<ScrollViewer DockPanel.Dock="Right" Width="260"> |
|||
<StackPanel Margin="12" Spacing="8"> |
|||
<TextBlock Text="Configuration" FontWeight="SemiBold" FontSize="16" |
|||
Foreground="{DynamicResource SystemControlHighlightAccentBrush}" /> |
|||
<TextBlock Text="Container Width" FontWeight="SemiBold" /> |
|||
<Slider x:Name="WidthSlider" |
|||
Minimum="120" |
|||
Maximum="700" |
|||
Value="400" |
|||
ValueChanged="OnWidthChanged" /> |
|||
<TextBlock x:Name="WidthLabel" |
|||
Text="400" |
|||
HorizontalAlignment="Center" |
|||
Opacity="0.7" /> |
|||
|
|||
<Separator /> |
|||
|
|||
<CheckBox x:Name="DynamicOverflowCheck" |
|||
Content="IsDynamicOverflowEnabled" |
|||
IsChecked="True" |
|||
IsCheckedChanged="OnDynamicOverflowChanged" /> |
|||
|
|||
<Separator /> |
|||
|
|||
<TextBlock Text="Overflow Priority" FontWeight="SemiBold" /> |
|||
<TextBlock Text="DynamicOverflowOrder priority (lower = stays visible longer):" |
|||
FontSize="12" Opacity="0.7" TextWrapping="Wrap" /> |
|||
<TextBlock Text="0: New, Save (always shown last to overflow)" FontSize="11" Opacity="0.7" /> |
|||
<TextBlock Text="1: Share" FontSize="11" Opacity="0.7" /> |
|||
<TextBlock Text="2: Bold, Italic" FontSize="11" Opacity="0.7" /> |
|||
<TextBlock Text="3: Delete (overflows first)" FontSize="11" Opacity="0.7" /> |
|||
</StackPanel> |
|||
</ScrollViewer> |
|||
|
|||
<Border DockPanel.Dock="Right" Width="1" Background="{DynamicResource SystemControlForegroundBaseMediumLowBrush}" /> |
|||
|
|||
<StackPanel Margin="12" Spacing="8"> |
|||
<TextBlock x:Name="StatusText" |
|||
Text="Showing 6 of 6 commands, 0 in overflow" |
|||
FontSize="12" |
|||
Opacity="0.7" /> |
|||
<Border x:Name="BarContainer" |
|||
Width="400" |
|||
HorizontalAlignment="Left" |
|||
BorderBrush="{DynamicResource SystemControlForegroundBaseMediumLowBrush}" |
|||
BorderThickness="1" |
|||
CornerRadius="4" |
|||
ClipToBounds="True"> |
|||
<CommandBar x:Name="DemoBar" IsDynamicOverflowEnabled="True"> |
|||
<CommandBar.PrimaryCommands> |
|||
<AppBarButton Label="New" DynamicOverflowOrder="0"><AppBarButton.Icon><PathIcon Data="{StaticResource AddIcon}" /></AppBarButton.Icon></AppBarButton> |
|||
<AppBarButton Label="Save" DynamicOverflowOrder="0"><AppBarButton.Icon><PathIcon Data="{StaticResource SaveIcon}" /></AppBarButton.Icon></AppBarButton> |
|||
<AppBarButton Label="Share" DynamicOverflowOrder="1"><AppBarButton.Icon><PathIcon Data="{StaticResource ShareIcon}" /></AppBarButton.Icon></AppBarButton> |
|||
<AppBarButton Label="Bold" DynamicOverflowOrder="2"><AppBarButton.Icon><PathIcon Data="{StaticResource BoldIcon}" /></AppBarButton.Icon></AppBarButton> |
|||
<AppBarButton Label="Italic" DynamicOverflowOrder="2"><AppBarButton.Icon><PathIcon Data="{StaticResource ItalicIcon}" /></AppBarButton.Icon></AppBarButton> |
|||
<AppBarButton Label="Delete" DynamicOverflowOrder="3"><AppBarButton.Icon><PathIcon Data="{StaticResource DeleteIcon}" /></AppBarButton.Icon></AppBarButton> |
|||
</CommandBar.PrimaryCommands> |
|||
</CommandBar> |
|||
</Border> |
|||
</StackPanel> |
|||
</DockPanel> |
|||
</UserControl> |
|||
@ -0,0 +1,45 @@ |
|||
using System.Collections.Specialized; |
|||
using Avalonia.Controls; |
|||
using Avalonia.Interactivity; |
|||
|
|||
namespace ControlCatalog.Pages |
|||
{ |
|||
public partial class CommandBarDynamicOverflowPage : UserControl |
|||
{ |
|||
public CommandBarDynamicOverflowPage() |
|||
{ |
|||
InitializeComponent(); |
|||
((INotifyCollectionChanged)DemoBar.OverflowItems).CollectionChanged += OnOverflowChanged; |
|||
UpdateStatus(); |
|||
} |
|||
|
|||
private void OnWidthChanged(object? sender, Avalonia.Controls.Primitives.RangeBaseValueChangedEventArgs e) |
|||
{ |
|||
if (BarContainer == null) |
|||
return; |
|||
var width = (int)WidthSlider.Value; |
|||
BarContainer.Width = width; |
|||
WidthLabel.Text = $"{width}"; |
|||
} |
|||
|
|||
private void OnDynamicOverflowChanged(object? sender, RoutedEventArgs e) |
|||
{ |
|||
if (DemoBar == null) |
|||
return; |
|||
DemoBar.IsDynamicOverflowEnabled = DynamicOverflowCheck.IsChecked == true; |
|||
} |
|||
|
|||
private void OnOverflowChanged(object? sender, NotifyCollectionChangedEventArgs e) |
|||
{ |
|||
UpdateStatus(); |
|||
} |
|||
|
|||
private void UpdateStatus() |
|||
{ |
|||
var total = DemoBar.PrimaryCommands.Count; |
|||
var overflow = DemoBar.OverflowItems.Count; |
|||
var visible = total - overflow; |
|||
StatusText.Text = $"Showing {visible} of {total} commands, {overflow} in overflow"; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,94 @@ |
|||
<UserControl xmlns="https://github.com/avaloniaui" |
|||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
|||
x:Class="ControlCatalog.Pages.CommandBarFirstLookPage"> |
|||
<UserControl.Resources> |
|||
<StreamGeometry x:Key="AddIcon">M19,13H13V19H11V13H5V11H11V5H13V11H19V13Z</StreamGeometry> |
|||
<StreamGeometry x:Key="SaveIcon">M15,9H5V5H15M12,19A3,3 0 0,1 9,16A3,3 0 0,1 12,13A3,3 0 0,1 15,16A3,3 0 0,1 12,19M17,3H5C3.89,3 3,3.9 3,5V19A2,2 0 0,0 5,21H19A2,2 0 0,0 21,19V7L17,3Z</StreamGeometry> |
|||
<StreamGeometry x:Key="ShareIcon">M18,16.08C17.24,16.08 16.56,16.38 16.04,16.85L8.91,12.7C8.96,12.47 9,12.24 9,12C9,11.76 8.96,11.53 8.91,11.3L15.96,7.19C16.5,7.69 17.21,8 18,8A3,3 0 0,0 21,5A3,3 0 0,0 18,2A3,3 0 0,0 15,5C15,5.24 15.04,5.47 15.09,5.7L8.04,9.81C7.5,9.31 6.79,9 6,9A3,3 0 0,0 3,12A3,3 0 0,0 6,15C6.79,15 7.5,14.69 8.04,14.19L15.16,18.34C15.11,18.55 15.08,18.77 15.08,19C15.08,20.61 16.39,21.91 18,21.91C19.61,21.91 20.92,20.61 20.92,19C20.92,17.39 19.61,16.08 18,16.08Z</StreamGeometry> |
|||
<StreamGeometry x:Key="BoldIcon">M15.6,10.79C17.04,10.07 18,8.64 18,7C18,4.79 16.21,3 14,3H7V21H14.73C16.78,21 18.5,19.37 18.5,17.32C18.5,15.82 17.72,14.53 16.5,13.77C16.2,13.59 15.9,13.44 15.6,13.32V10.79M10,6.5H13C13.83,6.5 14.5,7.17 14.5,8C14.5,8.83 13.83,9.5 13,9.5H10V6.5M13.5,17.5H10V14H13.5C14.33,14 15,14.67 15,15.5C15,16.33 14.33,17.5 13.5,17.5Z</StreamGeometry> |
|||
<StreamGeometry x:Key="ItalicIcon">M10,4V7H12.21L8.79,15H6V18H14V15H11.79L15.21,7H18V4H10Z</StreamGeometry> |
|||
<StreamGeometry x:Key="ExportIcon">M14,2H6A2,2 0 0,0 4,4V20A2,2 0 0,0 6,22H18A2,2 0 0,0 20,20V8L14,2M18,20H6V4H13V9H18V20M16,11V18.1L13.9,16L11.1,18.8L8.3,16L11.1,13.2L9,11.1L16,11Z</StreamGeometry> |
|||
<StreamGeometry x:Key="PrintIcon">M18,3H6V7H18M19,12A1,1 0 0,1 18,11A1,1 0 0,1 19,10A1,1 0 0,1 20,11A1,1 0 0,1 19,12M16,19H8V14H16M19,8H5A3,3 0 0,0 2,11V17H6V21H18V17H22V11A3,3 0 0,0 19,8Z</StreamGeometry> |
|||
<StreamGeometry x:Key="DeleteIcon">M19,4H15.5L14.5,3H9.5L8.5,4H5V6H19M6,19A2,2 0 0,0 8,21H16A2,2 0 0,0 18,19V7H6V19Z</StreamGeometry> |
|||
</UserControl.Resources> |
|||
|
|||
<DockPanel> |
|||
<ScrollViewer DockPanel.Dock="Right" Width="260"> |
|||
<StackPanel Margin="12" Spacing="8"> |
|||
<TextBlock Text="Configuration" FontWeight="SemiBold" FontSize="16" |
|||
Foreground="{DynamicResource SystemControlHighlightAccentBrush}" /> |
|||
<TextBlock Text="Primary Commands" FontWeight="SemiBold" /> |
|||
<TextBlock Text="Buttons displayed directly in the bar: New, Save, Bold, Italic, Share." |
|||
FontSize="12" Opacity="0.7" TextWrapping="Wrap" /> |
|||
|
|||
<Separator /> |
|||
|
|||
<TextBlock Text="Secondary Commands" FontWeight="SemiBold" /> |
|||
<TextBlock Text="Buttons in the overflow menu (three-dot icon): Export, Print, Delete." |
|||
FontSize="12" Opacity="0.7" TextWrapping="Wrap" /> |
|||
|
|||
<Separator /> |
|||
|
|||
<TextBlock Text="Content Area" FontWeight="SemiBold" /> |
|||
<TextBlock Text="Custom content (e.g. 'Document Editor' text) displayed on the left side of the bar." |
|||
FontSize="12" Opacity="0.7" TextWrapping="Wrap" /> |
|||
|
|||
<Separator /> |
|||
|
|||
<TextBlock Text="Separators" FontWeight="SemiBold" /> |
|||
<TextBlock Text="AppBarSeparator creates visual dividers between command groups." |
|||
FontSize="12" Opacity="0.7" TextWrapping="Wrap" /> |
|||
</StackPanel> |
|||
</ScrollViewer> |
|||
|
|||
<Border DockPanel.Dock="Right" Width="1" Background="{DynamicResource SystemControlForegroundBaseMediumLowBrush}" /> |
|||
|
|||
<ScrollViewer> |
|||
<StackPanel Spacing="12" Margin="12,12,12,0"> |
|||
<TextBlock Classes="h2">A toolbar supporting primary and secondary commands with an optional overflow menu.</TextBlock> |
|||
|
|||
<CommandBar> |
|||
<CommandBar.Content> |
|||
<TextBlock Text="Document Editor" VerticalAlignment="Center" Margin="8,0" /> |
|||
</CommandBar.Content> |
|||
<CommandBar.PrimaryCommands> |
|||
<AppBarButton Label="New" Click="OnButtonClick"> |
|||
<AppBarButton.Icon><PathIcon Data="{StaticResource AddIcon}" /></AppBarButton.Icon> |
|||
</AppBarButton> |
|||
<AppBarButton Label="Save" Click="OnButtonClick"> |
|||
<AppBarButton.Icon><PathIcon Data="{StaticResource SaveIcon}" /></AppBarButton.Icon> |
|||
</AppBarButton> |
|||
<AppBarSeparator /> |
|||
<AppBarToggleButton Label="Bold" IsCheckedChanged="OnToggleChanged"> |
|||
<AppBarToggleButton.Icon><PathIcon Data="{StaticResource BoldIcon}" /></AppBarToggleButton.Icon> |
|||
</AppBarToggleButton> |
|||
<AppBarToggleButton Label="Italic" IsCheckedChanged="OnToggleChanged"> |
|||
<AppBarToggleButton.Icon><PathIcon Data="{StaticResource ItalicIcon}" /></AppBarToggleButton.Icon> |
|||
</AppBarToggleButton> |
|||
<AppBarSeparator /> |
|||
<AppBarButton Label="Share" Click="OnButtonClick"> |
|||
<AppBarButton.Icon><PathIcon Data="{StaticResource ShareIcon}" /></AppBarButton.Icon> |
|||
</AppBarButton> |
|||
</CommandBar.PrimaryCommands> |
|||
<CommandBar.SecondaryCommands> |
|||
<AppBarButton Label="Export" Click="OnButtonClick"> |
|||
<AppBarButton.Icon><PathIcon Data="{StaticResource ExportIcon}" /></AppBarButton.Icon> |
|||
</AppBarButton> |
|||
<AppBarButton Label="Print" Click="OnButtonClick"> |
|||
<AppBarButton.Icon><PathIcon Data="{StaticResource PrintIcon}" /></AppBarButton.Icon> |
|||
</AppBarButton> |
|||
<AppBarSeparator /> |
|||
<AppBarButton Label="Delete" Click="OnButtonClick"> |
|||
<AppBarButton.Icon><PathIcon Data="{StaticResource DeleteIcon}" /></AppBarButton.Icon> |
|||
</AppBarButton> |
|||
</CommandBar.SecondaryCommands> |
|||
</CommandBar> |
|||
|
|||
<TextBlock x:Name="StatusText" |
|||
Text="Ready" |
|||
FontSize="13" |
|||
Opacity="0.7" /> |
|||
</StackPanel> |
|||
</ScrollViewer> |
|||
</DockPanel> |
|||
</UserControl> |
|||
@ -0,0 +1,27 @@ |
|||
using Avalonia.Controls; |
|||
using Avalonia.Interactivity; |
|||
|
|||
namespace ControlCatalog.Pages |
|||
{ |
|||
public partial class CommandBarFirstLookPage : UserControl |
|||
{ |
|||
public CommandBarFirstLookPage() |
|||
{ |
|||
InitializeComponent(); |
|||
} |
|||
|
|||
private void OnButtonClick(object? sender, RoutedEventArgs e) |
|||
{ |
|||
if (sender is AppBarButton btn) |
|||
StatusText.Text = $"{btn.Label} clicked"; |
|||
} |
|||
|
|||
private void OnToggleChanged(object? sender, RoutedEventArgs e) |
|||
{ |
|||
if (sender is AppBarToggleButton btn) |
|||
StatusText.Text = btn.IsChecked == true |
|||
? $"{btn.Label} enabled" |
|||
: $"{btn.Label} disabled"; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,47 @@ |
|||
<UserControl xmlns="https://github.com/avaloniaui" |
|||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
|||
x:Class="ControlCatalog.Pages.CommandBarLabelPositionPage"> |
|||
<UserControl.Resources> |
|||
<StreamGeometry x:Key="AddIcon">M19,13H13V19H11V13H5V11H11V5H13V11H19V13Z</StreamGeometry> |
|||
<StreamGeometry x:Key="SaveIcon">M15,9H5V5H15M12,19A3,3 0 0,1 9,16A3,3 0 0,1 12,13A3,3 0 0,1 15,16A3,3 0 0,1 12,19M17,3H5C3.89,3 3,3.9 3,5V19A2,2 0 0,0 5,21H19A2,2 0 0,0 21,19V7L17,3Z</StreamGeometry> |
|||
<StreamGeometry x:Key="ShareIcon">M18,16.08C17.24,16.08 16.56,16.38 16.04,16.85L8.91,12.7C8.96,12.47 9,12.24 9,12C9,11.76 8.96,11.53 8.91,11.3L15.96,7.19C16.5,7.69 17.21,8 18,8A3,3 0 0,0 21,5A3,3 0 0,0 18,2A3,3 0 0,0 15,5C15,5.24 15.04,5.47 15.09,5.7L8.04,9.81C7.5,9.31 6.79,9 6,9A3,3 0 0,0 3,12A3,3 0 0,0 6,15C6.79,15 7.5,14.69 8.04,14.19L15.16,18.34C15.11,18.55 15.08,18.77 15.08,19C15.08,20.61 16.39,21.91 18,21.91C19.61,21.91 20.92,20.61 20.92,19C20.92,17.39 19.61,16.08 18,16.08Z</StreamGeometry> |
|||
<StreamGeometry x:Key="DeleteIcon">M19,4H15.5L14.5,3H9.5L8.5,4H5V6H19M6,19A2,2 0 0,0 8,21H16A2,2 0 0,0 18,19V7H6V19Z</StreamGeometry> |
|||
</UserControl.Resources> |
|||
|
|||
<ScrollViewer> |
|||
<StackPanel Spacing="16" Margin="12,12,12,0"> |
|||
<TextBlock Classes="h2">The DefaultLabelPosition property controls how button labels are displayed.</TextBlock> |
|||
|
|||
<TextBlock Text="Bottom (default)" FontWeight="SemiBold" /> |
|||
<TextBlock Text="Label appears below the icon." FontSize="12" Opacity="0.7" /> |
|||
<CommandBar DefaultLabelPosition="Bottom" OverflowButtonVisibility="Collapsed"> |
|||
<AppBarButton Label="New"><AppBarButton.Icon><PathIcon Data="{StaticResource AddIcon}" /></AppBarButton.Icon></AppBarButton> |
|||
<AppBarButton Label="Save"><AppBarButton.Icon><PathIcon Data="{StaticResource SaveIcon}" /></AppBarButton.Icon></AppBarButton> |
|||
<AppBarButton Label="Share"><AppBarButton.Icon><PathIcon Data="{StaticResource ShareIcon}" /></AppBarButton.Icon></AppBarButton> |
|||
<AppBarButton Label="Delete"><AppBarButton.Icon><PathIcon Data="{StaticResource DeleteIcon}" /></AppBarButton.Icon></AppBarButton> |
|||
</CommandBar> |
|||
|
|||
<Separator /> |
|||
|
|||
<TextBlock Text="Right" FontWeight="SemiBold" /> |
|||
<TextBlock Text="Label appears to the right of the icon." FontSize="12" Opacity="0.7" /> |
|||
<CommandBar DefaultLabelPosition="Right" OverflowButtonVisibility="Collapsed"> |
|||
<AppBarButton Label="New"><AppBarButton.Icon><PathIcon Data="{StaticResource AddIcon}" /></AppBarButton.Icon></AppBarButton> |
|||
<AppBarButton Label="Save"><AppBarButton.Icon><PathIcon Data="{StaticResource SaveIcon}" /></AppBarButton.Icon></AppBarButton> |
|||
<AppBarButton Label="Share"><AppBarButton.Icon><PathIcon Data="{StaticResource ShareIcon}" /></AppBarButton.Icon></AppBarButton> |
|||
<AppBarButton Label="Delete"><AppBarButton.Icon><PathIcon Data="{StaticResource DeleteIcon}" /></AppBarButton.Icon></AppBarButton> |
|||
</CommandBar> |
|||
|
|||
<Separator /> |
|||
|
|||
<TextBlock Text="Collapsed (icon only)" FontWeight="SemiBold" /> |
|||
<TextBlock Text="No label shown. Use ToolTip.Tip to preserve accessibility." FontSize="12" Opacity="0.7" /> |
|||
<CommandBar DefaultLabelPosition="Collapsed" OverflowButtonVisibility="Collapsed"> |
|||
<AppBarButton ToolTip.Tip="New"><AppBarButton.Icon><PathIcon Data="{StaticResource AddIcon}" /></AppBarButton.Icon></AppBarButton> |
|||
<AppBarButton ToolTip.Tip="Save"><AppBarButton.Icon><PathIcon Data="{StaticResource SaveIcon}" /></AppBarButton.Icon></AppBarButton> |
|||
<AppBarButton ToolTip.Tip="Share"><AppBarButton.Icon><PathIcon Data="{StaticResource ShareIcon}" /></AppBarButton.Icon></AppBarButton> |
|||
<AppBarButton ToolTip.Tip="Delete"><AppBarButton.Icon><PathIcon Data="{StaticResource DeleteIcon}" /></AppBarButton.Icon></AppBarButton> |
|||
</CommandBar> |
|||
</StackPanel> |
|||
</ScrollViewer> |
|||
</UserControl> |
|||
@ -0,0 +1,12 @@ |
|||
using Avalonia.Controls; |
|||
|
|||
namespace ControlCatalog.Pages |
|||
{ |
|||
public partial class CommandBarLabelPositionPage : UserControl |
|||
{ |
|||
public CommandBarLabelPositionPage() |
|||
{ |
|||
InitializeComponent(); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,74 @@ |
|||
<UserControl xmlns="https://github.com/avaloniaui" |
|||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
|||
x:Class="ControlCatalog.Pages.CommandBarOverflowPage"> |
|||
<UserControl.Resources> |
|||
<StreamGeometry x:Key="AddIcon">M19,13H13V19H11V13H5V11H11V5H13V11H19V13Z</StreamGeometry> |
|||
<StreamGeometry x:Key="SaveIcon">M15,9H5V5H15M12,19A3,3 0 0,1 9,16A3,3 0 0,1 12,13A3,3 0 0,1 15,16A3,3 0 0,1 12,19M17,3H5C3.89,3 3,3.9 3,5V19A2,2 0 0,0 5,21H19A2,2 0 0,0 21,19V7L17,3Z</StreamGeometry> |
|||
<StreamGeometry x:Key="ShareIcon">M18,16.08C17.24,16.08 16.56,16.38 16.04,16.85L8.91,12.7C8.96,12.47 9,12.24 9,12C9,11.76 8.96,11.53 8.91,11.3L15.96,7.19C16.5,7.69 17.21,8 18,8A3,3 0 0,0 21,5A3,3 0 0,0 18,2A3,3 0 0,0 15,5C15,5.24 15.04,5.47 15.09,5.7L8.04,9.81C7.5,9.31 6.79,9 6,9A3,3 0 0,0 3,12A3,3 0 0,0 6,15C6.79,15 7.5,14.69 8.04,14.19L15.16,18.34C15.11,18.55 15.08,18.77 15.08,19C15.08,20.61 16.39,21.91 18,21.91C19.61,21.91 20.92,20.61 20.92,19C20.92,17.39 19.61,16.08 18,16.08Z</StreamGeometry> |
|||
<StreamGeometry x:Key="ExportIcon">M14,2H6A2,2 0 0,0 4,4V20A2,2 0 0,0 6,22H18A2,2 0 0,0 20,20V8L14,2M18,20H6V4H13V9H18V20M16,11V18.1L13.9,16L11.1,18.8L8.3,16L11.1,13.2L9,11.1L16,11Z</StreamGeometry> |
|||
<StreamGeometry x:Key="DeleteIcon">M19,4H15.5L14.5,3H9.5L8.5,4H5V6H19M6,19A2,2 0 0,0 8,21H16A2,2 0 0,0 18,19V7H6V19Z</StreamGeometry> |
|||
</UserControl.Resources> |
|||
|
|||
<DockPanel> |
|||
<ScrollViewer DockPanel.Dock="Right" Width="260"> |
|||
<StackPanel Margin="12" Spacing="8"> |
|||
<TextBlock Text="Configuration" FontWeight="SemiBold" FontSize="16" |
|||
Foreground="{DynamicResource SystemControlHighlightAccentBrush}" /> |
|||
<TextBlock Text="OverflowButtonVisibility" /> |
|||
<ComboBox x:Name="OverflowVisCombo" |
|||
SelectedIndex="0" |
|||
HorizontalAlignment="Stretch" |
|||
SelectionChanged="OnOverflowVisChanged"> |
|||
<ComboBoxItem Content="Auto" /> |
|||
<ComboBoxItem Content="Visible" /> |
|||
<ComboBoxItem Content="Collapsed" /> |
|||
</ComboBox> |
|||
|
|||
<CheckBox x:Name="IsOpenCheck" |
|||
Content="IsOpen" |
|||
IsCheckedChanged="OnIsOpenChanged" /> |
|||
|
|||
<CheckBox x:Name="IsStickyCheck" |
|||
Content="IsSticky" |
|||
IsCheckedChanged="OnIsStickyChanged" /> |
|||
|
|||
<Separator /> |
|||
|
|||
<Button Content="+ Add Primary" |
|||
HorizontalAlignment="Stretch" |
|||
Click="OnAddPrimary" /> |
|||
<Button Content="+ Add Secondary" |
|||
HorizontalAlignment="Stretch" |
|||
Click="OnAddSecondary" /> |
|||
|
|||
<Separator /> |
|||
|
|||
<TextBlock Text="About" FontWeight="SemiBold" /> |
|||
<TextBlock Text="Auto: overflow button shows when secondary commands exist. Visible: always show. Collapsed: never show." |
|||
FontSize="12" Opacity="0.7" TextWrapping="Wrap" /> |
|||
<TextBlock Text="IsSticky prevents the overflow from closing when clicking outside." |
|||
FontSize="12" Opacity="0.7" TextWrapping="Wrap" Margin="0,4,0,0" /> |
|||
</StackPanel> |
|||
</ScrollViewer> |
|||
|
|||
<Border DockPanel.Dock="Right" Width="1" Background="{DynamicResource SystemControlForegroundBaseMediumLowBrush}" /> |
|||
|
|||
<ScrollViewer> |
|||
<StackPanel Spacing="12" Margin="12,12,12,0"> |
|||
<TextBlock Classes="h2">The overflow (···) button reveals secondary commands. Configure its visibility and behavior.</TextBlock> |
|||
|
|||
<CommandBar x:Name="DemoBar" IsDynamicOverflowEnabled="True"> |
|||
<CommandBar.PrimaryCommands> |
|||
<AppBarButton Label="New"><AppBarButton.Icon><PathIcon Data="{StaticResource AddIcon}" /></AppBarButton.Icon></AppBarButton> |
|||
<AppBarButton Label="Save"><AppBarButton.Icon><PathIcon Data="{StaticResource SaveIcon}" /></AppBarButton.Icon></AppBarButton> |
|||
<AppBarButton Label="Share"><AppBarButton.Icon><PathIcon Data="{StaticResource ShareIcon}" /></AppBarButton.Icon></AppBarButton> |
|||
</CommandBar.PrimaryCommands> |
|||
<CommandBar.SecondaryCommands> |
|||
<AppBarButton Label="Export"><AppBarButton.Icon><PathIcon Data="{StaticResource ExportIcon}" /></AppBarButton.Icon></AppBarButton> |
|||
<AppBarButton Label="Delete"><AppBarButton.Icon><PathIcon Data="{StaticResource DeleteIcon}" /></AppBarButton.Icon></AppBarButton> |
|||
</CommandBar.SecondaryCommands> |
|||
</CommandBar> |
|||
</StackPanel> |
|||
</ScrollViewer> |
|||
</DockPanel> |
|||
</UserControl> |
|||
@ -0,0 +1,54 @@ |
|||
using Avalonia.Controls; |
|||
using Avalonia.Interactivity; |
|||
|
|||
namespace ControlCatalog.Pages |
|||
{ |
|||
public partial class CommandBarOverflowPage : UserControl |
|||
{ |
|||
private int _primaryCount; |
|||
private int _secondaryCount; |
|||
|
|||
public CommandBarOverflowPage() |
|||
{ |
|||
InitializeComponent(); |
|||
} |
|||
|
|||
private void OnOverflowVisChanged(object? sender, SelectionChangedEventArgs e) |
|||
{ |
|||
if (DemoBar == null) |
|||
return; |
|||
DemoBar.OverflowButtonVisibility = OverflowVisCombo.SelectedIndex switch |
|||
{ |
|||
1 => CommandBarOverflowButtonVisibility.Visible, |
|||
2 => CommandBarOverflowButtonVisibility.Collapsed, |
|||
_ => CommandBarOverflowButtonVisibility.Auto |
|||
}; |
|||
} |
|||
|
|||
private void OnIsOpenChanged(object? sender, RoutedEventArgs e) |
|||
{ |
|||
if (DemoBar == null) |
|||
return; |
|||
DemoBar.IsOpen = IsOpenCheck.IsChecked == true; |
|||
} |
|||
|
|||
private void OnIsStickyChanged(object? sender, RoutedEventArgs e) |
|||
{ |
|||
if (DemoBar == null) |
|||
return; |
|||
DemoBar.IsSticky = IsStickyCheck.IsChecked == true; |
|||
} |
|||
|
|||
private void OnAddPrimary(object? sender, RoutedEventArgs e) |
|||
{ |
|||
_primaryCount++; |
|||
DemoBar.PrimaryCommands.Add(new AppBarButton { Label = $"Cmd {_primaryCount}" }); |
|||
} |
|||
|
|||
private void OnAddSecondary(object? sender, RoutedEventArgs e) |
|||
{ |
|||
_secondaryCount++; |
|||
DemoBar.SecondaryCommands.Add(new AppBarButton { Label = $"Sec {_secondaryCount}" }); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,77 @@ |
|||
<UserControl xmlns="https://github.com/avaloniaui" |
|||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
|||
x:Class="ControlCatalog.Pages.CommandBarTogglePage"> |
|||
<UserControl.Resources> |
|||
<StreamGeometry x:Key="BoldIcon">M15.6,10.79C17.04,10.07 18,8.64 18,7C18,4.79 16.21,3 14,3H7V21H14.73C16.78,21 18.5,19.37 18.5,17.32C18.5,15.82 17.72,14.53 16.5,13.77C16.2,13.59 15.9,13.44 15.6,13.32V10.79M10,6.5H13C13.83,6.5 14.5,7.17 14.5,8C14.5,8.83 13.83,9.5 13,9.5H10V6.5M13.5,17.5H10V14H13.5C14.33,14 15,14.67 15,15.5C15,16.33 14.33,17.5 13.5,17.5Z</StreamGeometry> |
|||
<StreamGeometry x:Key="ItalicIcon">M10,4V7H12.21L8.79,15H6V18H14V15H11.79L15.21,7H18V4H10Z</StreamGeometry> |
|||
<StreamGeometry x:Key="UnderlineIcon">M5,21H19V19H5V21M12,17A6,6 0 0,0 18,11V3H15.5V11A3.5,3.5 0 0,1 12,14.5A3.5,3.5 0 0,1 8.5,11V3H6V11A6,6 0 0,0 12,17Z</StreamGeometry> |
|||
<StreamGeometry x:Key="FavoriteIcon">M12,21.35L10.55,20.03C5.4,15.36 2,12.27 2,8.5C2,5.41 4.42,3 7.5,3C9.24,3 10.91,3.81 12,5.08C13.09,3.81 14.76,3 16.5,3C19.58,3 22,5.41 22,8.5C22,12.27 18.6,15.36 13.45,20.03L12,21.35Z</StreamGeometry> |
|||
</UserControl.Resources> |
|||
|
|||
<DockPanel> |
|||
<ScrollViewer DockPanel.Dock="Right" Width="260"> |
|||
<StackPanel Margin="12" Spacing="8"> |
|||
<TextBlock Text="Configuration" FontWeight="SemiBold" FontSize="16" |
|||
Foreground="{DynamicResource SystemControlHighlightAccentBrush}" /> |
|||
<TextBlock Text="Toggle State" FontWeight="SemiBold" FontSize="13" /> |
|||
|
|||
<CheckBox x:Name="ForceBoldCheck" |
|||
Content="Bold" |
|||
IsCheckedChanged="OnForceBoldChanged" /> |
|||
<CheckBox x:Name="ForceItalicCheck" |
|||
Content="Italic" |
|||
IsCheckedChanged="OnForceItalicChanged" /> |
|||
<CheckBox x:Name="ForceUnderlineCheck" |
|||
Content="Underline" |
|||
IsCheckedChanged="OnForceUnderlineChanged" /> |
|||
|
|||
<Separator /> |
|||
|
|||
<TextBlock Text="About" FontWeight="SemiBold" /> |
|||
<TextBlock Text="AppBarToggleButton maintains checked/unchecked state. When checked, it shows a highlight background. Bind IsChecked to a boolean property." |
|||
FontSize="12" Opacity="0.7" TextWrapping="Wrap" /> |
|||
</StackPanel> |
|||
</ScrollViewer> |
|||
|
|||
<Border DockPanel.Dock="Right" Width="1" Background="{DynamicResource SystemControlForegroundBaseMediumLowBrush}" /> |
|||
|
|||
<ScrollViewer> |
|||
<StackPanel Spacing="12" Margin="12,12,12,0"> |
|||
<TextBlock Classes="h2">AppBarToggleButton supports on/off states for formatting and feature toggles.</TextBlock> |
|||
|
|||
<TextBlock Text="Text Formatting" FontWeight="SemiBold" /> |
|||
<CommandBar x:Name="FormatBar" OverflowButtonVisibility="Collapsed"> |
|||
<AppBarToggleButton x:Name="BoldToggle" |
|||
Label="Bold" |
|||
IsCheckedChanged="OnFormatChanged"> |
|||
<AppBarToggleButton.Icon><PathIcon Data="{StaticResource BoldIcon}" /></AppBarToggleButton.Icon> |
|||
</AppBarToggleButton> |
|||
<AppBarToggleButton x:Name="ItalicToggle" |
|||
Label="Italic" |
|||
IsCheckedChanged="OnFormatChanged"> |
|||
<AppBarToggleButton.Icon><PathIcon Data="{StaticResource ItalicIcon}" /></AppBarToggleButton.Icon> |
|||
</AppBarToggleButton> |
|||
<AppBarToggleButton x:Name="UnderlineToggle" |
|||
Label="Underline" |
|||
IsCheckedChanged="OnFormatChanged"> |
|||
<AppBarToggleButton.Icon><PathIcon Data="{StaticResource UnderlineIcon}" /></AppBarToggleButton.Icon> |
|||
</AppBarToggleButton> |
|||
</CommandBar> |
|||
|
|||
<TextBlock x:Name="FormatStatus" |
|||
Text="Active: (none)" |
|||
FontSize="13" |
|||
Opacity="0.7" /> |
|||
|
|||
<Separator /> |
|||
|
|||
<TextBlock Text="Favorite" FontWeight="SemiBold" /> |
|||
<CommandBar OverflowButtonVisibility="Collapsed"> |
|||
<AppBarToggleButton Label="Favorite"> |
|||
<AppBarToggleButton.Icon><PathIcon Data="{StaticResource FavoriteIcon}" /></AppBarToggleButton.Icon> |
|||
</AppBarToggleButton> |
|||
</CommandBar> |
|||
</StackPanel> |
|||
</ScrollViewer> |
|||
</DockPanel> |
|||
</UserControl> |
|||
@ -0,0 +1,50 @@ |
|||
using System.Collections.Generic; |
|||
using Avalonia.Controls; |
|||
using Avalonia.Interactivity; |
|||
|
|||
namespace ControlCatalog.Pages |
|||
{ |
|||
public partial class CommandBarTogglePage : UserControl |
|||
{ |
|||
public CommandBarTogglePage() |
|||
{ |
|||
InitializeComponent(); |
|||
} |
|||
|
|||
private void OnFormatChanged(object? sender, RoutedEventArgs e) |
|||
{ |
|||
if (FormatStatus == null) |
|||
return; |
|||
var active = new List<string>(); |
|||
if (BoldToggle.IsChecked == true) active.Add("Bold"); |
|||
if (ItalicToggle.IsChecked == true) active.Add("Italic"); |
|||
if (UnderlineToggle.IsChecked == true) active.Add("Underline"); |
|||
FormatStatus.Text = active.Count > 0 ? $"Active: {string.Join(", ", active)}" : "Active: (none)"; |
|||
|
|||
ForceBoldCheck.IsChecked = BoldToggle.IsChecked; |
|||
ForceItalicCheck.IsChecked = ItalicToggle.IsChecked; |
|||
ForceUnderlineCheck.IsChecked = UnderlineToggle.IsChecked; |
|||
} |
|||
|
|||
private void OnForceBoldChanged(object? sender, RoutedEventArgs e) |
|||
{ |
|||
if (BoldToggle == null) |
|||
return; |
|||
BoldToggle.IsChecked = ForceBoldCheck.IsChecked; |
|||
} |
|||
|
|||
private void OnForceItalicChanged(object? sender, RoutedEventArgs e) |
|||
{ |
|||
if (ItalicToggle == null) |
|||
return; |
|||
ItalicToggle.IsChecked = ForceItalicCheck.IsChecked; |
|||
} |
|||
|
|||
private void OnForceUnderlineChanged(object? sender, RoutedEventArgs e) |
|||
{ |
|||
if (UnderlineToggle == null) |
|||
return; |
|||
UnderlineToggle.IsChecked = ForceUnderlineCheck.IsChecked; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,8 @@ |
|||
<UserControl xmlns="https://github.com/avaloniaui" |
|||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
|||
x:Class="ControlCatalog.Pages.CommandBarPage"> |
|||
<UserControl.Resources> |
|||
<SolidColorBrush x:Key="NavigationBarBackground" Color="Transparent" /> |
|||
</UserControl.Resources> |
|||
<NavigationPage x:Name="SampleNav" /> |
|||
</UserControl> |
|||
@ -0,0 +1,158 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using Avalonia.Controls; |
|||
using Avalonia.Interactivity; |
|||
using Avalonia.Layout; |
|||
using Avalonia.Media; |
|||
|
|||
namespace ControlCatalog.Pages |
|||
{ |
|||
public partial class CommandBarPage : UserControl |
|||
{ |
|||
private static readonly (string Group, string Title, string Description, Func<UserControl> Factory)[] Demos = |
|||
{ |
|||
// Overview
|
|||
("Overview", "First Look", "A CommandBar with primary commands, secondary overflow menu, and custom content area.", () => new CommandBarFirstLookPage()), |
|||
("Overview", "Toggle Buttons", "AppBarToggleButton for stateful actions like Bold, Italic, and Favorite.", () => new CommandBarTogglePage()), |
|||
|
|||
// Appearance
|
|||
("Appearance", "Label Positions", "Configure label position: Bottom (default), Right, or Collapsed (icon only).", () => new CommandBarLabelPositionPage()), |
|||
("Appearance", "Customization", "Background, Foreground, BorderBrush, BorderThickness, and CornerRadius.", () => new CommandBarCustomizationPage()), |
|||
|
|||
// Features
|
|||
("Features", "Overflow Menu", "Secondary commands appear in an overflow popup. Configure visibility and sticky behavior.", () => new CommandBarOverflowPage()), |
|||
("Features", "Dynamic Overflow", "IsDynamicOverflowEnabled moves primary commands to overflow as space shrinks.", () => new CommandBarDynamicOverflowPage()), |
|||
}; |
|||
|
|||
public CommandBarPage() |
|||
{ |
|||
InitializeComponent(); |
|||
Loaded += OnLoaded; |
|||
} |
|||
|
|||
private async void OnLoaded(object? sender, RoutedEventArgs e) |
|||
{ |
|||
await SampleNav.PushAsync(CreateHomePage(), null); |
|||
} |
|||
|
|||
private ContentPage CreateHomePage() |
|||
{ |
|||
var stack = new StackPanel |
|||
{ |
|||
Margin = new Avalonia.Thickness(12), |
|||
Spacing = 16 |
|||
}; |
|||
|
|||
var groups = new Dictionary<string, WrapPanel>(); |
|||
var groupOrder = new List<string>(); |
|||
|
|||
foreach (var (group, title, description, factory) in Demos) |
|||
{ |
|||
if (!groups.ContainsKey(group)) |
|||
{ |
|||
groups[group] = new WrapPanel |
|||
{ |
|||
Orientation = Orientation.Horizontal, |
|||
HorizontalAlignment = HorizontalAlignment.Left |
|||
}; |
|||
groupOrder.Add(group); |
|||
} |
|||
|
|||
var demoFactory = factory; |
|||
var demoTitle = title; |
|||
|
|||
var card = new Button |
|||
{ |
|||
Width = 170, |
|||
MinHeight = 80, |
|||
Margin = new Avalonia.Thickness(0, 0, 8, 8), |
|||
VerticalAlignment = VerticalAlignment.Top, |
|||
HorizontalContentAlignment = HorizontalAlignment.Left, |
|||
VerticalContentAlignment = VerticalAlignment.Top, |
|||
Padding = new Avalonia.Thickness(12, 8), |
|||
Content = new StackPanel |
|||
{ |
|||
Spacing = 4, |
|||
Children = |
|||
{ |
|||
new TextBlock |
|||
{ |
|||
Text = title, |
|||
FontSize = 13, |
|||
FontWeight = FontWeight.SemiBold, |
|||
TextWrapping = TextWrapping.Wrap |
|||
}, |
|||
new TextBlock |
|||
{ |
|||
Text = description, |
|||
FontSize = 11, |
|||
Opacity = 0.6, |
|||
TextWrapping = TextWrapping.Wrap |
|||
} |
|||
} |
|||
} |
|||
}; |
|||
|
|||
card.Click += async (s, e) => |
|||
{ |
|||
var headerGrid = new Grid { ColumnDefinitions = new ColumnDefinitions("*, Auto") }; |
|||
headerGrid.Children.Add(new TextBlock |
|||
{ |
|||
Text = demoTitle, |
|||
VerticalAlignment = VerticalAlignment.Center |
|||
}); |
|||
var closeBtn = new Button |
|||
{ |
|||
Content = new PathIcon |
|||
{ |
|||
Data = Geometry.Parse("M4.397 4.397a1 1 0 0 1 1.414 0L12 10.585l6.19-6.188a1 1 0 0 1 1.414 1.414L13.413 12l6.19 6.189a1 1 0 0 1-1.414 1.414L12 13.413l-6.189 6.19a1 1 0 0 1-1.414-1.414L10.585 12 4.397 5.811a1 1 0 0 1 0-1.414z") |
|||
}, |
|||
Background = Brushes.Transparent, |
|||
BorderThickness = new Avalonia.Thickness(0), |
|||
Padding = new Avalonia.Thickness(8, 4), |
|||
VerticalAlignment = VerticalAlignment.Center |
|||
}; |
|||
Grid.SetColumn(closeBtn, 1); |
|||
headerGrid.Children.Add(closeBtn); |
|||
closeBtn.Click += async (_, _) => await SampleNav.PopAsync(null); |
|||
|
|||
var page = new ContentPage |
|||
{ |
|||
Header = headerGrid, |
|||
Content = demoFactory(), |
|||
HorizontalContentAlignment = HorizontalAlignment.Stretch, |
|||
VerticalContentAlignment = VerticalAlignment.Stretch |
|||
}; |
|||
NavigationPage.SetHasBackButton(page, false); |
|||
await SampleNav.PushAsync(page, null); |
|||
}; |
|||
|
|||
groups[group].Children.Add(card); |
|||
} |
|||
|
|||
foreach (var groupName in groupOrder) |
|||
{ |
|||
stack.Children.Add(new TextBlock |
|||
{ |
|||
Text = groupName, |
|||
FontSize = 13, |
|||
FontWeight = FontWeight.SemiBold, |
|||
Margin = new Avalonia.Thickness(0, 0, 0, 4), |
|||
Opacity = 0.6 |
|||
}); |
|||
stack.Children.Add(groups[groupName]); |
|||
} |
|||
|
|||
var homePage = new ContentPage |
|||
{ |
|||
Content = new ScrollViewer { Content = stack }, |
|||
HorizontalContentAlignment = HorizontalAlignment.Stretch, |
|||
VerticalContentAlignment = VerticalAlignment.Stretch |
|||
}; |
|||
|
|||
NavigationPage.SetHasNavigationBar(homePage, false); |
|||
|
|||
return homePage; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,11 @@ |
|||
<UserControl x:Class="ControlCatalog.Pages.ConnectedAnimationDemoPage" |
|||
xmlns="https://github.com/avaloniaui" |
|||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> |
|||
<NavigationPage x:Name="SampleNav"> |
|||
<NavigationPage.Styles> |
|||
<Style Selector="NavigationPage#SampleNav /template/ Border#PART_NavigationBar"> |
|||
<Setter Property="Background" Value="Transparent" /> |
|||
</Style> |
|||
</NavigationPage.Styles> |
|||
</NavigationPage> |
|||
</UserControl> |
|||
@ -0,0 +1,144 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using Avalonia.Controls; |
|||
using Avalonia.Interactivity; |
|||
using Avalonia.Layout; |
|||
using Avalonia.Media; |
|||
|
|||
namespace ControlCatalog.Pages |
|||
{ |
|||
public partial class ConnectedAnimationDemoPage : UserControl |
|||
{ |
|||
private static readonly (string Group, string Title, string Description, Func<UserControl> Factory)[] Demos = []; |
|||
|
|||
public ConnectedAnimationDemoPage() |
|||
{ |
|||
InitializeComponent(); |
|||
Loaded += OnLoaded; |
|||
} |
|||
|
|||
private async void OnLoaded(object? sender, RoutedEventArgs e) |
|||
{ |
|||
await SampleNav.PushAsync(CreateHomePage(), null); |
|||
} |
|||
|
|||
private ContentPage CreateHomePage() |
|||
{ |
|||
var stack = new StackPanel |
|||
{ |
|||
Margin = new Avalonia.Thickness(12), |
|||
Spacing = 16 |
|||
}; |
|||
|
|||
var groups = new Dictionary<string, WrapPanel>(); |
|||
var groupOrder = new List<string>(); |
|||
|
|||
foreach (var (group, title, description, factory) in Demos) |
|||
{ |
|||
if (!groups.ContainsKey(group)) |
|||
{ |
|||
groups[group] = new WrapPanel |
|||
{ |
|||
Orientation = Orientation.Horizontal, |
|||
HorizontalAlignment = HorizontalAlignment.Left |
|||
}; |
|||
groupOrder.Add(group); |
|||
} |
|||
|
|||
var demoFactory = factory; |
|||
var demoTitle = title; |
|||
|
|||
var card = new Button |
|||
{ |
|||
Width = 200, |
|||
MinHeight = 80, |
|||
Margin = new Avalonia.Thickness(0, 0, 8, 8), |
|||
VerticalAlignment = VerticalAlignment.Top, |
|||
HorizontalContentAlignment = HorizontalAlignment.Left, |
|||
VerticalContentAlignment = VerticalAlignment.Top, |
|||
Padding = new Avalonia.Thickness(12, 8), |
|||
Content = new StackPanel |
|||
{ |
|||
Spacing = 4, |
|||
Children = |
|||
{ |
|||
new TextBlock |
|||
{ |
|||
Text = title, |
|||
FontSize = 13, |
|||
FontWeight = FontWeight.SemiBold, |
|||
TextWrapping = TextWrapping.Wrap |
|||
}, |
|||
new TextBlock |
|||
{ |
|||
Text = description, |
|||
FontSize = 11, |
|||
Opacity = 0.6, |
|||
TextWrapping = TextWrapping.Wrap |
|||
} |
|||
} |
|||
} |
|||
}; |
|||
|
|||
card.Click += async (s, ev) => |
|||
{ |
|||
var headerGrid = new Grid { ColumnDefinitions = new ColumnDefinitions("*, Auto") }; |
|||
headerGrid.Children.Add(new TextBlock |
|||
{ |
|||
Text = demoTitle, |
|||
VerticalAlignment = VerticalAlignment.Center |
|||
}); |
|||
var closeBtn = new Button |
|||
{ |
|||
Content = new PathIcon |
|||
{ |
|||
Data = Geometry.Parse("M4.397 4.397a1 1 0 0 1 1.414 0L12 10.585l6.19-6.188a1 1 0 0 1 1.414 1.414L13.413 12l6.19 6.189a1 1 0 0 1-1.414 1.414L12 13.413l-6.189 6.19a1 1 0 0 1-1.414-1.414L10.585 12 4.397 5.811a1 1 0 0 1 0-1.414z") |
|||
}, |
|||
Background = Brushes.Transparent, |
|||
BorderThickness = new Avalonia.Thickness(0), |
|||
Padding = new Avalonia.Thickness(8, 4), |
|||
VerticalAlignment = VerticalAlignment.Center |
|||
}; |
|||
Grid.SetColumn(closeBtn, 1); |
|||
headerGrid.Children.Add(closeBtn); |
|||
closeBtn.Click += async (_, _) => await SampleNav.PopAsync(null); |
|||
|
|||
var page = new ContentPage |
|||
{ |
|||
Header = headerGrid, |
|||
Content = demoFactory(), |
|||
HorizontalContentAlignment = HorizontalAlignment.Stretch, |
|||
VerticalContentAlignment = VerticalAlignment.Stretch |
|||
}; |
|||
NavigationPage.SetHasBackButton(page, false); |
|||
await SampleNav.PushAsync(page, null); |
|||
}; |
|||
|
|||
groups[group].Children.Add(card); |
|||
} |
|||
|
|||
foreach (var groupName in groupOrder) |
|||
{ |
|||
stack.Children.Add(new TextBlock |
|||
{ |
|||
Text = groupName, |
|||
FontSize = 13, |
|||
FontWeight = FontWeight.SemiBold, |
|||
Margin = new Avalonia.Thickness(0, 0, 0, 4), |
|||
Opacity = 0.6 |
|||
}); |
|||
stack.Children.Add(groups[groupName]); |
|||
} |
|||
|
|||
var homePage = new ContentPage |
|||
{ |
|||
Content = new ScrollViewer { Content = stack }, |
|||
HorizontalContentAlignment = HorizontalAlignment.Stretch, |
|||
VerticalContentAlignment = VerticalAlignment.Stretch |
|||
}; |
|||
|
|||
NavigationPage.SetHasNavigationBar(homePage, false); |
|||
return homePage; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,11 @@ |
|||
<UserControl xmlns="https://github.com/avaloniaui" |
|||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
|||
x:Class="ControlCatalog.Pages.ContentDemoPage"> |
|||
<NavigationPage x:Name="SampleNav"> |
|||
<NavigationPage.Styles> |
|||
<Style Selector="NavigationPage#SampleNav /template/ Border#PART_NavigationBar"> |
|||
<Setter Property="Background" Value="Transparent" /> |
|||
</Style> |
|||
</NavigationPage.Styles> |
|||
</NavigationPage> |
|||
</UserControl> |
|||
@ -0,0 +1,160 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using Avalonia.Controls; |
|||
using Avalonia.Interactivity; |
|||
using Avalonia.Layout; |
|||
using Avalonia.Media; |
|||
|
|||
namespace ControlCatalog.Pages |
|||
{ |
|||
public partial class ContentDemoPage : UserControl |
|||
{ |
|||
private static readonly (string Group, string Title, string Description, Func<UserControl> Factory)[] Demos = |
|||
{ |
|||
// Overview
|
|||
("Overview", "First Look", "Basic ContentPage with header, content, and background inside a NavigationPage.", () => new ContentPageFirstLookPage()), |
|||
|
|||
// Appearance
|
|||
("Appearance", "Customization", "Adjust content alignment, background color, and padding to understand how ContentPage adapts its layout.", () => new ContentPageCustomizationPage()), |
|||
|
|||
// Features
|
|||
("Features", "CommandBar", "Attach a CommandBar to the top or bottom of a ContentPage. Add and remove items at runtime.", () => new ContentPageCommandBarPage()), |
|||
("Features", "Safe Area", "Understand how AutomaticallyApplySafeAreaPadding absorbs platform insets.", () => new ContentPageSafeAreaPage()), |
|||
("Features", "Events", "Observe page lifecycle events: NavigatedTo, NavigatedFrom, and Navigating.", () => new ContentPageEventsPage()), |
|||
|
|||
// Performance
|
|||
("Performance", "Performance Monitor", "Push ContentPages of varying weight (50 KB to 2 MB) and observe live instance count and managed heap. Pop pages and force GC to confirm memory is released.", () => new ContentPagePerformancePage()), |
|||
}; |
|||
|
|||
public ContentDemoPage() |
|||
{ |
|||
InitializeComponent(); |
|||
Loaded += OnLoaded; |
|||
} |
|||
|
|||
private async void OnLoaded(object? sender, RoutedEventArgs e) |
|||
{ |
|||
await SampleNav.PushAsync(CreateHomePage(), null); |
|||
} |
|||
|
|||
private ContentPage CreateHomePage() |
|||
{ |
|||
var stack = new StackPanel |
|||
{ |
|||
Margin = new Avalonia.Thickness(12), |
|||
Spacing = 16 |
|||
}; |
|||
|
|||
var groups = new Dictionary<string, WrapPanel>(); |
|||
var groupOrder = new List<string>(); |
|||
|
|||
foreach (var (group, title, description, factory) in Demos) |
|||
{ |
|||
if (!groups.ContainsKey(group)) |
|||
{ |
|||
groups[group] = new WrapPanel |
|||
{ |
|||
Orientation = Orientation.Horizontal, |
|||
HorizontalAlignment = HorizontalAlignment.Left |
|||
}; |
|||
groupOrder.Add(group); |
|||
} |
|||
|
|||
var demoFactory = factory; |
|||
var demoTitle = title; |
|||
|
|||
var card = new Button |
|||
{ |
|||
Width = 170, |
|||
MinHeight = 80, |
|||
Margin = new Avalonia.Thickness(0, 0, 8, 8), |
|||
VerticalAlignment = VerticalAlignment.Top, |
|||
HorizontalContentAlignment = HorizontalAlignment.Left, |
|||
VerticalContentAlignment = VerticalAlignment.Top, |
|||
Padding = new Avalonia.Thickness(12, 8), |
|||
Content = new StackPanel |
|||
{ |
|||
Spacing = 4, |
|||
Children = |
|||
{ |
|||
new TextBlock |
|||
{ |
|||
Text = title, |
|||
FontSize = 13, |
|||
FontWeight = FontWeight.SemiBold, |
|||
TextWrapping = TextWrapping.Wrap |
|||
}, |
|||
new TextBlock |
|||
{ |
|||
Text = description, |
|||
FontSize = 11, |
|||
Opacity = 0.6, |
|||
TextWrapping = TextWrapping.Wrap |
|||
} |
|||
} |
|||
} |
|||
}; |
|||
|
|||
card.Click += async (s, e) => |
|||
{ |
|||
var headerGrid = new Grid { ColumnDefinitions = new ColumnDefinitions("*, Auto") }; |
|||
headerGrid.Children.Add(new TextBlock |
|||
{ |
|||
Text = demoTitle, |
|||
VerticalAlignment = VerticalAlignment.Center |
|||
}); |
|||
var closeBtn = new Button |
|||
{ |
|||
Content = new PathIcon |
|||
{ |
|||
Data = Geometry.Parse("M4.397 4.397a1 1 0 0 1 1.414 0L12 10.585l6.19-6.188a1 1 0 0 1 1.414 1.414L13.413 12l6.19 6.189a1 1 0 0 1-1.414 1.414L12 13.413l-6.189 6.19a1 1 0 0 1-1.414-1.414L10.585 12 4.397 5.811a1 1 0 0 1 0-1.414z") |
|||
}, |
|||
Background = Brushes.Transparent, |
|||
BorderThickness = new Avalonia.Thickness(0), |
|||
Padding = new Avalonia.Thickness(8, 4), |
|||
VerticalAlignment = VerticalAlignment.Center |
|||
}; |
|||
Grid.SetColumn(closeBtn, 1); |
|||
headerGrid.Children.Add(closeBtn); |
|||
closeBtn.Click += async (_, _) => await SampleNav.PopAsync(null); |
|||
|
|||
var page = new ContentPage |
|||
{ |
|||
Header = headerGrid, |
|||
Content = demoFactory(), |
|||
HorizontalContentAlignment = HorizontalAlignment.Stretch, |
|||
VerticalContentAlignment = VerticalAlignment.Stretch |
|||
}; |
|||
NavigationPage.SetHasBackButton(page, false); |
|||
await SampleNav.PushAsync(page, null); |
|||
}; |
|||
|
|||
groups[group].Children.Add(card); |
|||
} |
|||
|
|||
foreach (var groupName in groupOrder) |
|||
{ |
|||
stack.Children.Add(new TextBlock |
|||
{ |
|||
Text = groupName, |
|||
FontSize = 13, |
|||
FontWeight = FontWeight.SemiBold, |
|||
Margin = new Avalonia.Thickness(0, 0, 0, 4), |
|||
Opacity = 0.6 |
|||
}); |
|||
stack.Children.Add(groups[groupName]); |
|||
} |
|||
|
|||
var homePage = new ContentPage |
|||
{ |
|||
Content = new ScrollViewer { Content = stack }, |
|||
HorizontalContentAlignment = HorizontalAlignment.Stretch, |
|||
VerticalContentAlignment = VerticalAlignment.Stretch |
|||
}; |
|||
|
|||
NavigationPage.SetHasNavigationBar(homePage, false); |
|||
|
|||
return homePage; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,63 @@ |
|||
<UserControl xmlns="https://github.com/avaloniaui" |
|||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
|||
x:Class="ControlCatalog.Pages.ContentPageCommandBarPage"> |
|||
<DockPanel> |
|||
<ScrollViewer DockPanel.Dock="Right" Width="260"> |
|||
<StackPanel Margin="12" Spacing="8"> |
|||
<TextBlock Text="Configuration" FontWeight="SemiBold" FontSize="16" |
|||
Foreground="{DynamicResource SystemControlHighlightAccentBrush}" /> |
|||
|
|||
<TextBlock Text="Position" FontWeight="SemiBold" /> |
|||
<ComboBox x:Name="PositionCombo" |
|||
SelectedIndex="0" |
|||
HorizontalAlignment="Stretch" |
|||
SelectionChanged="OnPositionChanged"> |
|||
<ComboBoxItem Content="Top" /> |
|||
<ComboBoxItem Content="Bottom" /> |
|||
</ComboBox> |
|||
|
|||
<Separator /> |
|||
|
|||
<TextBlock Text="Manage Items" FontWeight="SemiBold" /> |
|||
<CheckBox x:Name="UseIconCheck" Content="Use Icon (primary items)" /> |
|||
<Button Content="Add Primary Item" HorizontalAlignment="Stretch" Click="OnAddPrimary" /> |
|||
<Button Content="Add Secondary Item" HorizontalAlignment="Stretch" Click="OnAddSecondary" /> |
|||
<Button Content="Add Separator" HorizontalAlignment="Stretch" Click="OnAddSeparator" /> |
|||
<Button Content="Clear All" HorizontalAlignment="Stretch" Click="OnClearAll" /> |
|||
|
|||
<Separator /> |
|||
|
|||
<TextBlock Text="Navigation" FontWeight="SemiBold" /> |
|||
<Button Content="Push Page" HorizontalAlignment="Stretch" Click="OnPush" /> |
|||
<Button Content="Pop Page" HorizontalAlignment="Stretch" Click="OnPop" /> |
|||
|
|||
<Separator /> |
|||
|
|||
<TextBlock Text="About" FontWeight="SemiBold" /> |
|||
<TextBlock Text="• NavigationPage.SetTopCommandBar(page, bar): places a CommandBar inside the navigation bar area at the top." |
|||
FontSize="12" Opacity="0.7" TextWrapping="Wrap" /> |
|||
<TextBlock Text="• NavigationPage.SetBottomCommandBar(page, bar): places a CommandBar below the page content at the bottom." |
|||
FontSize="12" Opacity="0.7" TextWrapping="Wrap" /> |
|||
<TextBlock Text="• Each ContentPage has its own CommandBar. It is replaced when navigating between pages." |
|||
FontSize="12" Opacity="0.7" TextWrapping="Wrap" /> |
|||
</StackPanel> |
|||
</ScrollViewer> |
|||
|
|||
<Border DockPanel.Dock="Right" Width="1" Background="{DynamicResource SystemControlForegroundBaseMediumLowBrush}" /> |
|||
|
|||
<Grid Margin="12" RowDefinitions="Auto,*"> |
|||
<TextBlock x:Name="StatusText" |
|||
Text="No items added" |
|||
FontSize="12" |
|||
Opacity="0.7" |
|||
Margin="0,0,0,8" /> |
|||
<Border Grid.Row="1" |
|||
BorderBrush="{DynamicResource SystemControlForegroundBaseMediumLowBrush}" |
|||
BorderThickness="1" |
|||
CornerRadius="6" |
|||
ClipToBounds="True"> |
|||
<NavigationPage x:Name="DemoNav" /> |
|||
</Border> |
|||
</Grid> |
|||
</DockPanel> |
|||
</UserControl> |
|||
@ -0,0 +1,212 @@ |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Threading.Tasks; |
|||
using Avalonia.Controls; |
|||
using Avalonia.Interactivity; |
|||
using Avalonia.Layout; |
|||
using Avalonia.Media; |
|||
|
|||
namespace ControlCatalog.Pages |
|||
{ |
|||
public partial class ContentPageCommandBarPage : UserControl |
|||
{ |
|||
private static readonly (string Label, string PathData)[] IconPresets = |
|||
{ |
|||
("Add", "M19,13H13V19H11V13H5V11H11V5H13V11H19V13Z"), |
|||
("Save", "M15,9H5V5H15M12,19A3,3 0 0,1 9,16A3,3 0 0,1 12,13A3,3 0 0,1 15,16A3,3 0 0,1 12,19M17,3H5C3.89,3 3,3.9 3,5V19A2,2 0 0,0 5,21H19A2,2 0 0,0 21,19V7L17,3Z"), |
|||
("Share", "M18,16.08C17.24,16.08 16.56,16.38 16.04,16.85L8.91,12.7C8.96,12.47 9,12.24 9,12C9,11.76 8.96,11.53 8.91,11.3L15.96,7.19C16.5,7.69 17.21,8 18,8A3,3 0 0,0 21,5A3,3 0 0,0 18,2A3,3 0 0,0 15,5C15,5.24 15.04,5.47 15.09,5.7L8.04,9.81C7.5,9.31 6.79,9 6,9A3,3 0 0,0 3,12A3,3 0 0,0 6,15C6.79,15 7.5,14.69 8.04,14.19L15.16,18.34C15.11,18.55 15.08,18.77 15.08,19C15.08,20.61 16.39,21.91 18,21.91C19.61,21.91 20.92,20.61 20.92,19C20.92,17.39 19.61,16.08 18,16.08Z"), |
|||
("Favorite", "M12,21.35L10.55,20.03C5.4,15.36 2,12.27 2,8.5C2,5.41 4.42,3 7.5,3C9.24,3 10.91,3.81 12,5.08C13.09,3.81 14.76,3 16.5,3C19.58,3 22,5.41 22,8.5C22,12.27 18.6,15.36 13.45,20.03L12,21.35Z"), |
|||
("Delete", "M19,4H15.5L14.5,3H9.5L8.5,4H5V6H19M6,19A2,2 0 0,0 8,21H16A2,2 0 0,0 18,19V7H6V19Z"), |
|||
}; |
|||
|
|||
private int _itemCounter; |
|||
private string _position = "Top"; |
|||
private readonly List<ICommandBarElement> _primaryItems = new(); |
|||
private readonly List<ICommandBarElement> _secondaryItems = new(); |
|||
|
|||
public ContentPageCommandBarPage() |
|||
{ |
|||
InitializeComponent(); |
|||
Loaded += OnLoaded; |
|||
} |
|||
|
|||
private async void OnLoaded(object? sender, RoutedEventArgs e) |
|||
{ |
|||
var rootPage = new ContentPage |
|||
{ |
|||
Header = "CommandBar Demo", |
|||
Background = new SolidColorBrush(Color.Parse("#E3F2FD")), |
|||
Content = new StackPanel |
|||
{ |
|||
HorizontalAlignment = HorizontalAlignment.Center, |
|||
VerticalAlignment = VerticalAlignment.Center, |
|||
Spacing = 12, |
|||
Children = |
|||
{ |
|||
new TextBlock |
|||
{ |
|||
Text = "Root Page", |
|||
FontSize = 24, |
|||
FontWeight = FontWeight.Bold, |
|||
HorizontalAlignment = HorizontalAlignment.Center, |
|||
}, |
|||
new TextBlock |
|||
{ |
|||
Text = "Add items using the panel on the right,\nthen change the position to Top or Bottom.", |
|||
FontSize = 14, |
|||
TextWrapping = TextWrapping.Wrap, |
|||
HorizontalAlignment = HorizontalAlignment.Center, |
|||
TextAlignment = TextAlignment.Center, |
|||
Opacity = 0.7, |
|||
} |
|||
} |
|||
}, |
|||
HorizontalContentAlignment = HorizontalAlignment.Stretch, |
|||
VerticalContentAlignment = VerticalAlignment.Stretch |
|||
}; |
|||
await DemoNav.PushAsync(rootPage); |
|||
} |
|||
|
|||
private void OnPositionChanged(object? sender, SelectionChangedEventArgs e) |
|||
{ |
|||
if (PositionCombo == null) |
|||
return; |
|||
_position = PositionCombo.SelectedIndex == 1 ? "Bottom" : "Top"; |
|||
RebuildCommandBar(); |
|||
} |
|||
|
|||
private void OnAddPrimary(object? sender, RoutedEventArgs e) |
|||
{ |
|||
_itemCounter++; |
|||
var btn = new AppBarButton { Label = $"Action {_itemCounter}" }; |
|||
if (UseIconCheck.IsChecked == true) |
|||
{ |
|||
var preset = IconPresets[(_itemCounter - 1) % IconPresets.Length]; |
|||
btn.Label = preset.Label; |
|||
btn.Icon = new PathIcon { Data = StreamGeometry.Parse(preset.PathData) }; |
|||
btn.IsCompact = true; |
|||
} |
|||
_primaryItems.Add(btn); |
|||
RebuildCommandBar(); |
|||
} |
|||
|
|||
private void OnAddSecondary(object? sender, RoutedEventArgs e) |
|||
{ |
|||
_itemCounter++; |
|||
_secondaryItems.Add(new AppBarButton { Label = $"Item {_itemCounter}" }); |
|||
RebuildCommandBar(); |
|||
} |
|||
|
|||
private void OnAddSeparator(object? sender, RoutedEventArgs e) |
|||
{ |
|||
_primaryItems.Add(new AppBarSeparator()); |
|||
RebuildCommandBar(); |
|||
} |
|||
|
|||
private void OnClearAll(object? sender, RoutedEventArgs e) |
|||
{ |
|||
_primaryItems.Clear(); |
|||
_secondaryItems.Clear(); |
|||
_itemCounter = 0; |
|||
ClearCommandBarFromActivePage(); |
|||
StatusText.Text = "No items added"; |
|||
} |
|||
|
|||
private async void OnPush(object? sender, RoutedEventArgs e) |
|||
{ |
|||
var next = DemoNav.StackDepth + 1; |
|||
var page = new ContentPage |
|||
{ |
|||
Header = $"Page {next}", |
|||
Background = new SolidColorBrush(Color.Parse("#E8F5E9")), |
|||
Content = new StackPanel |
|||
{ |
|||
HorizontalAlignment = HorizontalAlignment.Center, |
|||
VerticalAlignment = VerticalAlignment.Center, |
|||
Spacing = 8, |
|||
Children = |
|||
{ |
|||
new TextBlock |
|||
{ |
|||
Text = $"Page {next}", |
|||
FontSize = 28, |
|||
FontWeight = FontWeight.Bold, |
|||
HorizontalAlignment = HorizontalAlignment.Center, |
|||
}, |
|||
new TextBlock |
|||
{ |
|||
Text = "New page: no CommandBar set", |
|||
FontSize = 14, |
|||
Opacity = 0.6, |
|||
HorizontalAlignment = HorizontalAlignment.Center, |
|||
} |
|||
} |
|||
}, |
|||
HorizontalContentAlignment = HorizontalAlignment.Stretch, |
|||
VerticalContentAlignment = VerticalAlignment.Stretch |
|||
}; |
|||
await DemoNav.PushAsync(page); |
|||
} |
|||
|
|||
private async void OnPop(object? sender, RoutedEventArgs e) => await DemoNav.PopAsync(); |
|||
|
|||
private void ClearCommandBarFromActivePage() |
|||
{ |
|||
if (DemoNav.CurrentPage is Page activePage) |
|||
{ |
|||
NavigationPage.SetTopCommandBar(activePage, null); |
|||
NavigationPage.SetBottomCommandBar(activePage, null); |
|||
} |
|||
} |
|||
|
|||
private void RebuildCommandBar() |
|||
{ |
|||
if (DemoNav == null || DemoNav.CurrentPage is not Page activePage) |
|||
return; |
|||
if (_primaryItems.Count == 0 && _secondaryItems.Count == 0) |
|||
{ |
|||
ClearCommandBarFromActivePage(); |
|||
StatusText.Text = "No items added"; |
|||
return; |
|||
} |
|||
|
|||
NavigationPage.SetTopCommandBar(activePage, null); |
|||
NavigationPage.SetBottomCommandBar(activePage, null); |
|||
|
|||
var commandBar = new CommandBar { IsDynamicOverflowEnabled = true }; |
|||
|
|||
foreach (var item in _primaryItems) |
|||
{ |
|||
if (item is AppBarButton btn) |
|||
{ |
|||
PathIcon? icon = null; |
|||
if (btn.Icon is PathIcon src) |
|||
icon = new PathIcon { Data = src.Data }; |
|||
commandBar.PrimaryCommands.Add(new AppBarButton |
|||
{ |
|||
Label = btn.Label, |
|||
Icon = icon, |
|||
IsCompact = btn.IsCompact, |
|||
}); |
|||
} |
|||
else if (item is AppBarSeparator) |
|||
commandBar.PrimaryCommands.Add(new AppBarSeparator()); |
|||
} |
|||
|
|||
foreach (var item in _secondaryItems) |
|||
{ |
|||
if (item is AppBarButton btn) |
|||
commandBar.SecondaryCommands.Add(new AppBarButton { Label = btn.Label }); |
|||
} |
|||
|
|||
if (_position == "Top") |
|||
NavigationPage.SetTopCommandBar(activePage, commandBar); |
|||
else |
|||
NavigationPage.SetBottomCommandBar(activePage, commandBar); |
|||
|
|||
var primaryCount = _primaryItems.Count(i => i is AppBarButton); |
|||
var secondaryCount = _secondaryItems.Count; |
|||
StatusText.Text = $"{primaryCount} primary, {secondaryCount} secondary ({_position})"; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,106 @@ |
|||
<UserControl xmlns="https://github.com/avaloniaui" |
|||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
|||
x:Class="ControlCatalog.Pages.ContentPageCustomizationPage"> |
|||
<DockPanel> |
|||
<ScrollViewer DockPanel.Dock="Right" Width="260"> |
|||
<StackPanel Margin="12" Spacing="8"> |
|||
<TextBlock Text="Configuration" FontWeight="SemiBold" FontSize="16" |
|||
Foreground="{DynamicResource SystemControlHighlightAccentBrush}" /> |
|||
|
|||
<TextBlock Text="Background" FontWeight="SemiBold" /> |
|||
<ComboBox x:Name="BackgroundCombo" |
|||
SelectedIndex="0" |
|||
HorizontalAlignment="Stretch" |
|||
SelectionChanged="OnBackgroundChanged"> |
|||
<ComboBoxItem Content="Default" /> |
|||
<ComboBoxItem Content="Light Blue" /> |
|||
<ComboBoxItem Content="Light Green" /> |
|||
<ComboBoxItem Content="Light Purple" /> |
|||
<ComboBoxItem Content="Warm White" /> |
|||
</ComboBox> |
|||
|
|||
<Separator /> |
|||
|
|||
<TextBlock Text="Horizontal Content Alignment" FontWeight="SemiBold" /> |
|||
<ComboBox x:Name="HAlignCombo" |
|||
SelectedIndex="3" |
|||
HorizontalAlignment="Stretch" |
|||
SelectionChanged="OnHAlignChanged"> |
|||
<ComboBoxItem Content="Left" /> |
|||
<ComboBoxItem Content="Center" /> |
|||
<ComboBoxItem Content="Right" /> |
|||
<ComboBoxItem Content="Stretch" /> |
|||
</ComboBox> |
|||
|
|||
<TextBlock Text="Vertical Content Alignment" FontWeight="SemiBold" /> |
|||
<ComboBox x:Name="VAlignCombo" |
|||
SelectedIndex="3" |
|||
HorizontalAlignment="Stretch" |
|||
SelectionChanged="OnVAlignChanged"> |
|||
<ComboBoxItem Content="Top" /> |
|||
<ComboBoxItem Content="Center" /> |
|||
<ComboBoxItem Content="Bottom" /> |
|||
<ComboBoxItem Content="Stretch" /> |
|||
</ComboBox> |
|||
|
|||
<Separator /> |
|||
|
|||
<TextBlock Text="Padding" FontWeight="SemiBold" /> |
|||
<Slider x:Name="PaddingSlider" |
|||
Minimum="0" |
|||
Maximum="48" |
|||
Value="0" |
|||
TickFrequency="8" |
|||
IsSnapToTickEnabled="True" |
|||
ValueChanged="OnPaddingChanged" /> |
|||
<TextBlock x:Name="PaddingLabel" |
|||
Text="0 px" |
|||
HorizontalAlignment="Center" |
|||
Opacity="0.7" /> |
|||
|
|||
<Separator /> |
|||
|
|||
<TextBlock Text="About" FontWeight="SemiBold" /> |
|||
<TextBlock Text="• HorizontalContentAlignment / VerticalContentAlignment position the content inside the page area." |
|||
FontSize="12" Opacity="0.7" TextWrapping="Wrap" /> |
|||
<TextBlock Text="• Padding adds space between the page border and its content presenter." |
|||
FontSize="12" Opacity="0.7" TextWrapping="Wrap" /> |
|||
<TextBlock Text="• Background accepts any Avalonia brush, including gradients." |
|||
FontSize="12" Opacity="0.7" TextWrapping="Wrap" /> |
|||
</StackPanel> |
|||
</ScrollViewer> |
|||
|
|||
<Border DockPanel.Dock="Right" Width="1" Background="{DynamicResource SystemControlForegroundBaseMediumLowBrush}" /> |
|||
|
|||
<Border Margin="12" |
|||
BorderBrush="{DynamicResource SystemControlForegroundBaseMediumLowBrush}" |
|||
BorderThickness="1" |
|||
CornerRadius="6" |
|||
ClipToBounds="True"> |
|||
<ContentPage x:Name="SamplePage" |
|||
Header="Customization" |
|||
HorizontalContentAlignment="Stretch" |
|||
VerticalContentAlignment="Stretch"> |
|||
<Border Background="#E0E0E0" |
|||
CornerRadius="8" |
|||
Padding="24" |
|||
Width="180" |
|||
Height="100"> |
|||
<StackPanel Spacing="4" |
|||
HorizontalAlignment="Center" |
|||
VerticalAlignment="Center"> |
|||
<TextBlock Text="Content Area" |
|||
FontSize="16" |
|||
FontWeight="SemiBold" |
|||
HorizontalAlignment="Center" /> |
|||
<TextBlock Text="Adjust alignment and padding" |
|||
FontSize="12" |
|||
Opacity="0.6" |
|||
TextWrapping="Wrap" |
|||
TextAlignment="Center" /> |
|||
</StackPanel> |
|||
</Border> |
|||
</ContentPage> |
|||
</Border> |
|||
</DockPanel> |
|||
</UserControl> |
|||
@ -0,0 +1,64 @@ |
|||
using Avalonia.Controls; |
|||
using Avalonia.Interactivity; |
|||
using Avalonia.Layout; |
|||
using Avalonia.Media; |
|||
|
|||
namespace ControlCatalog.Pages |
|||
{ |
|||
public partial class ContentPageCustomizationPage : UserControl |
|||
{ |
|||
public ContentPageCustomizationPage() |
|||
{ |
|||
InitializeComponent(); |
|||
} |
|||
|
|||
private void OnBackgroundChanged(object? sender, SelectionChangedEventArgs e) |
|||
{ |
|||
if (SamplePage == null) |
|||
return; |
|||
SamplePage.Background = BackgroundCombo.SelectedIndex switch |
|||
{ |
|||
1 => new SolidColorBrush(Color.Parse("#E3F2FD")), |
|||
2 => new SolidColorBrush(Color.Parse("#E8F5E9")), |
|||
3 => new SolidColorBrush(Color.Parse("#F3E5F5")), |
|||
4 => new SolidColorBrush(Color.Parse("#FFF8E1")), |
|||
_ => null |
|||
}; |
|||
} |
|||
|
|||
private void OnHAlignChanged(object? sender, SelectionChangedEventArgs e) |
|||
{ |
|||
if (SamplePage == null) |
|||
return; |
|||
SamplePage.HorizontalContentAlignment = HAlignCombo.SelectedIndex switch |
|||
{ |
|||
0 => HorizontalAlignment.Left, |
|||
1 => HorizontalAlignment.Center, |
|||
2 => HorizontalAlignment.Right, |
|||
_ => HorizontalAlignment.Stretch |
|||
}; |
|||
} |
|||
|
|||
private void OnVAlignChanged(object? sender, SelectionChangedEventArgs e) |
|||
{ |
|||
if (SamplePage == null) |
|||
return; |
|||
SamplePage.VerticalContentAlignment = VAlignCombo.SelectedIndex switch |
|||
{ |
|||
0 => VerticalAlignment.Top, |
|||
1 => VerticalAlignment.Center, |
|||
2 => VerticalAlignment.Bottom, |
|||
_ => VerticalAlignment.Stretch |
|||
}; |
|||
} |
|||
|
|||
private void OnPaddingChanged(object? sender, Avalonia.Controls.Primitives.RangeBaseValueChangedEventArgs e) |
|||
{ |
|||
if (SamplePage == null) |
|||
return; |
|||
var padding = (int)PaddingSlider.Value; |
|||
SamplePage.Padding = new Avalonia.Thickness(padding); |
|||
PaddingLabel.Text = $"{padding} px"; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,66 @@ |
|||
<UserControl xmlns="https://github.com/avaloniaui" |
|||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
|||
x:Class="ControlCatalog.Pages.ContentPageEventsPage"> |
|||
<DockPanel> |
|||
<ScrollViewer DockPanel.Dock="Right" Width="260"> |
|||
<StackPanel Margin="12" Spacing="8"> |
|||
|
|||
<TextBlock Text="Configuration" FontSize="16" FontWeight="SemiBold" |
|||
Foreground="{DynamicResource SystemControlHighlightAccentBrush}" /> |
|||
|
|||
<TextBlock Text="Navigation" FontSize="13" FontWeight="SemiBold" /> |
|||
<StackPanel Spacing="6"> |
|||
<Button Content="Push Page" HorizontalAlignment="Stretch" Click="OnPush" /> |
|||
<Button Content="Pop Page" HorizontalAlignment="Stretch" Click="OnPop" /> |
|||
</StackPanel> |
|||
|
|||
<Separator /> |
|||
|
|||
<TextBlock Text="Navigating (cancel)" FontSize="13" FontWeight="SemiBold" /> |
|||
<CheckBox x:Name="BlockNavCheck" Content="Block navigation" /> |
|||
<TextBlock Text="When checked, the Navigating handler sets Cancel=true and prevents the navigation from proceeding." |
|||
TextWrapping="Wrap" FontSize="11" Opacity="0.6" /> |
|||
|
|||
<Separator /> |
|||
|
|||
<DockPanel> |
|||
<TextBlock DockPanel.Dock="Left" Text="Event Log" FontSize="13" FontWeight="SemiBold" |
|||
VerticalAlignment="Center" /> |
|||
<Button DockPanel.Dock="Right" Content="Clear" Click="OnClearLog" |
|||
HorizontalAlignment="Right" Padding="8,2" FontSize="11" /> |
|||
</DockPanel> |
|||
<Border Background="{DynamicResource SystemControlBackgroundBaseLowBrush}" |
|||
CornerRadius="4" Padding="8" MinHeight="120" MaxHeight="300"> |
|||
<ScrollViewer x:Name="LogScrollViewer"> |
|||
<ItemsControl x:Name="EventLogItems"> |
|||
<ItemsControl.ItemTemplate> |
|||
<DataTemplate> |
|||
<TextBlock Text="{Binding}" |
|||
FontFamily="Cascadia Code,Consolas,Menlo,monospace" |
|||
FontSize="11" Margin="0,1" /> |
|||
</DataTemplate> |
|||
</ItemsControl.ItemTemplate> |
|||
</ItemsControl> |
|||
</ScrollViewer> |
|||
</Border> |
|||
|
|||
<Separator /> |
|||
|
|||
<TextBlock Text="About" FontSize="13" FontWeight="SemiBold" /> |
|||
<TextBlock TextWrapping="Wrap" FontSize="12" Opacity="0.7" |
|||
Text="ContentPage exposes lifecycle events directly on the page. NavigatedTo fires after the page arrives, providing the previous page and navigation type. NavigatedFrom fires after departure. Navigating fires before leaving and can cancel the navigation by setting Cancel=true." /> |
|||
|
|||
</StackPanel> |
|||
</ScrollViewer> |
|||
|
|||
<Border DockPanel.Dock="Right" Width="1" Background="{DynamicResource SystemControlForegroundBaseMediumLowBrush}" /> |
|||
|
|||
<Border Margin="12" |
|||
BorderBrush="{DynamicResource SystemControlForegroundBaseMediumLowBrush}" |
|||
BorderThickness="1" |
|||
CornerRadius="8" |
|||
ClipToBounds="True"> |
|||
<NavigationPage x:Name="DemoNav" /> |
|||
</Border> |
|||
</DockPanel> |
|||
</UserControl> |
|||
@ -0,0 +1,103 @@ |
|||
using System.Collections.ObjectModel; |
|||
using System.Threading.Tasks; |
|||
using Avalonia.Controls; |
|||
using Avalonia.Interactivity; |
|||
using Avalonia.Layout; |
|||
using Avalonia.Media; |
|||
|
|||
namespace ControlCatalog.Pages |
|||
{ |
|||
public partial class ContentPageEventsPage : UserControl |
|||
{ |
|||
private int _pageCount; |
|||
private readonly ObservableCollection<string> _logItems = new(); |
|||
|
|||
public ContentPageEventsPage() |
|||
{ |
|||
InitializeComponent(); |
|||
Loaded += OnLoaded; |
|||
} |
|||
|
|||
private async void OnLoaded(object? sender, RoutedEventArgs e) |
|||
{ |
|||
EventLogItems.ItemsSource = _logItems; |
|||
|
|||
var root = MakePage("Root", "Navigate to see lifecycle events in the log below."); |
|||
SubscribeEvents(root); |
|||
await DemoNav.PushAsync(root); |
|||
} |
|||
|
|||
private void SubscribeEvents(ContentPage page) |
|||
{ |
|||
page.NavigatedTo += (_, e) => AddLog($"[{page.Header}] NavigatedTo (type: {e.NavigationType})"); |
|||
page.NavigatedFrom += (_, _) => AddLog($"[{page.Header}] NavigatedFrom"); |
|||
page.Navigating += async args => |
|||
{ |
|||
if (BlockNavCheck.IsChecked == true) |
|||
{ |
|||
args.Cancel = true; |
|||
AddLog($"[{page.Header}] Navigating — BLOCKED"); |
|||
await Task.Delay(600); |
|||
args.Cancel = false; |
|||
AddLog($"[{page.Header}] Navigating — unblocked"); |
|||
} |
|||
else |
|||
{ |
|||
AddLog($"[{page.Header}] Navigating"); |
|||
} |
|||
}; |
|||
} |
|||
|
|||
private async void OnPush(object? sender, RoutedEventArgs e) |
|||
{ |
|||
_pageCount++; |
|||
var page = MakePage($"Page {_pageCount}", "Navigate back to see Navigating/NavigatedFrom."); |
|||
SubscribeEvents(page); |
|||
await DemoNav.PushAsync(page); |
|||
} |
|||
|
|||
private async void OnPop(object? sender, RoutedEventArgs e) => await DemoNav.PopAsync(); |
|||
|
|||
private void OnClearLog(object? sender, RoutedEventArgs e) => _logItems.Clear(); |
|||
|
|||
private void AddLog(string message) |
|||
{ |
|||
_logItems.Add(message); |
|||
LogScrollViewer.ScrollToEnd(); |
|||
} |
|||
|
|||
private static ContentPage MakePage(string header, string body) => |
|||
new ContentPage |
|||
{ |
|||
Header = header, |
|||
Content = new StackPanel |
|||
{ |
|||
HorizontalAlignment = HorizontalAlignment.Center, |
|||
VerticalAlignment = VerticalAlignment.Center, |
|||
Spacing = 8, |
|||
Children = |
|||
{ |
|||
new TextBlock |
|||
{ |
|||
Text = header, |
|||
FontSize = 24, |
|||
FontWeight = FontWeight.Bold, |
|||
HorizontalAlignment = HorizontalAlignment.Center, |
|||
}, |
|||
new TextBlock |
|||
{ |
|||
Text = body, |
|||
FontSize = 13, |
|||
Opacity = 0.6, |
|||
TextWrapping = TextWrapping.Wrap, |
|||
TextAlignment = TextAlignment.Center, |
|||
HorizontalAlignment = HorizontalAlignment.Center, |
|||
MaxWidth = 260, |
|||
} |
|||
} |
|||
}, |
|||
HorizontalContentAlignment = HorizontalAlignment.Stretch, |
|||
VerticalContentAlignment = VerticalAlignment.Stretch, |
|||
}; |
|||
} |
|||
} |
|||
@ -0,0 +1,48 @@ |
|||
<UserControl xmlns="https://github.com/avaloniaui" |
|||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
|||
x:Class="ControlCatalog.Pages.ContentPageFirstLookPage"> |
|||
<DockPanel> |
|||
<ScrollViewer DockPanel.Dock="Right" Width="260"> |
|||
<StackPanel Margin="12" Spacing="8"> |
|||
<TextBlock Text="Configuration" FontWeight="SemiBold" FontSize="16" |
|||
Foreground="{DynamicResource SystemControlHighlightAccentBrush}" /> |
|||
<TextBlock Text="ContentPage is the fundamental page type. It hosts a single piece of content and integrates with NavigationPage, TabbedPage, and CarouselPage. The Header property sets the navigation bar title." |
|||
FontSize="12" Opacity="0.7" TextWrapping="Wrap" /> |
|||
|
|||
<Separator /> |
|||
|
|||
<TextBlock Text="Navigation" FontWeight="SemiBold" /> |
|||
<Button Content="Push Page" HorizontalAlignment="Stretch" Click="OnPush" /> |
|||
<Button Content="Pop Page" HorizontalAlignment="Stretch" Click="OnPop" /> |
|||
<Button Content="Pop to Root" HorizontalAlignment="Stretch" Click="OnPopToRoot" /> |
|||
|
|||
<Separator /> |
|||
|
|||
<TextBlock Text="Key Properties" FontWeight="SemiBold" /> |
|||
<TextBlock Text="• Header: nav bar title (string or Control)" FontSize="12" Opacity="0.8" TextWrapping="Wrap" /> |
|||
<TextBlock Text="• Content: any Avalonia control" FontSize="12" Opacity="0.8" TextWrapping="Wrap" /> |
|||
<TextBlock Text="• Background: page background brush" FontSize="12" Opacity="0.8" TextWrapping="Wrap" /> |
|||
<TextBlock Text="• HorizontalContentAlignment" FontSize="12" Opacity="0.8" /> |
|||
<TextBlock Text="• VerticalContentAlignment" FontSize="12" Opacity="0.8" /> |
|||
<TextBlock Text="• AutomaticallyApplySafeAreaPadding" FontSize="12" Opacity="0.8" /> |
|||
|
|||
<Separator /> |
|||
|
|||
<TextBlock x:Name="StatusText" |
|||
Text="Depth: 1 | Current: Root Page" |
|||
FontSize="11" |
|||
Opacity="0.7" /> |
|||
</StackPanel> |
|||
</ScrollViewer> |
|||
|
|||
<Border DockPanel.Dock="Right" Width="1" Background="{DynamicResource SystemControlForegroundBaseMediumLowBrush}" /> |
|||
|
|||
<Border Margin="12" |
|||
BorderBrush="{DynamicResource SystemControlForegroundBaseMediumLowBrush}" |
|||
BorderThickness="1" |
|||
CornerRadius="6" |
|||
ClipToBounds="True"> |
|||
<NavigationPage x:Name="DemoNav" /> |
|||
</Border> |
|||
</DockPanel> |
|||
</UserControl> |
|||
@ -0,0 +1,93 @@ |
|||
using System.Threading.Tasks; |
|||
using Avalonia.Controls; |
|||
using Avalonia.Interactivity; |
|||
using Avalonia.Layout; |
|||
using Avalonia.Media; |
|||
|
|||
namespace ControlCatalog.Pages |
|||
{ |
|||
public partial class ContentPageFirstLookPage : UserControl |
|||
{ |
|||
private static readonly Color[] PageColors = |
|||
[ |
|||
Color.FromRgb(0xE3, 0xF2, 0xFD), // blue
|
|||
Color.FromRgb(0xF3, 0xE5, 0xF5), // purple
|
|||
Color.FromRgb(0xE8, 0xF5, 0xE9), // green
|
|||
Color.FromRgb(0xFF, 0xF8, 0xE1), // amber
|
|||
Color.FromRgb(0xFB, 0xE9, 0xE7), // deep orange
|
|||
]; |
|||
|
|||
private int _pageCount; |
|||
|
|||
public ContentPageFirstLookPage() |
|||
{ |
|||
InitializeComponent(); |
|||
Loaded += OnLoaded; |
|||
} |
|||
|
|||
private async void OnLoaded(object? sender, RoutedEventArgs e) |
|||
{ |
|||
await DemoNav.PushAsync(MakePage("Root Page", "ContentPage inside a NavigationPage.\nUse the options to navigate.")); |
|||
UpdateStatus(); |
|||
} |
|||
|
|||
private async void OnPush(object? sender, RoutedEventArgs e) |
|||
{ |
|||
_pageCount++; |
|||
await DemoNav.PushAsync(MakePage($"Page {_pageCount}", $"ContentPage #{_pageCount}.\nNavigate back using the back button.")); |
|||
UpdateStatus(); |
|||
} |
|||
|
|||
private async void OnPop(object? sender, RoutedEventArgs e) |
|||
{ |
|||
await DemoNav.PopAsync(); |
|||
UpdateStatus(); |
|||
} |
|||
|
|||
private async void OnPopToRoot(object? sender, RoutedEventArgs e) |
|||
{ |
|||
await DemoNav.PopToRootAsync(); |
|||
_pageCount = 0; |
|||
UpdateStatus(); |
|||
} |
|||
|
|||
private void UpdateStatus() |
|||
{ |
|||
StatusText.Text = $"Depth: {DemoNav.StackDepth} | Current: {DemoNav.CurrentPage?.Header}"; |
|||
} |
|||
|
|||
private ContentPage MakePage(string header, string body) => |
|||
new ContentPage |
|||
{ |
|||
Header = header, |
|||
Background = new SolidColorBrush(PageColors[_pageCount % PageColors.Length]), |
|||
Content = new StackPanel |
|||
{ |
|||
HorizontalAlignment = HorizontalAlignment.Center, |
|||
VerticalAlignment = VerticalAlignment.Center, |
|||
Spacing = 10, |
|||
Children = |
|||
{ |
|||
new TextBlock |
|||
{ |
|||
Text = header, |
|||
FontSize = 20, |
|||
FontWeight = FontWeight.SemiBold, |
|||
HorizontalAlignment = HorizontalAlignment.Center |
|||
}, |
|||
new TextBlock |
|||
{ |
|||
Text = body, |
|||
FontSize = 13, |
|||
Opacity = 0.7, |
|||
TextWrapping = TextWrapping.Wrap, |
|||
TextAlignment = TextAlignment.Center, |
|||
MaxWidth = 260 |
|||
} |
|||
} |
|||
}, |
|||
HorizontalContentAlignment = HorizontalAlignment.Stretch, |
|||
VerticalContentAlignment = VerticalAlignment.Stretch |
|||
}; |
|||
} |
|||
} |
|||
@ -0,0 +1,104 @@ |
|||
<UserControl xmlns="https://github.com/avaloniaui" |
|||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
|||
x:Class="ControlCatalog.Pages.ContentPagePerformancePage"> |
|||
<Grid ColumnDefinitions="*,300"> |
|||
|
|||
<!-- Left: NavigationPage + log --> |
|||
<DockPanel Grid.Column="0" Margin="16"> |
|||
<TextBlock DockPanel.Dock="Top" |
|||
Text="Push pages of varying weight and observe how GC reclaims memory after pop." |
|||
FontSize="13" Opacity="0.6" Margin="0,0,0,12" /> |
|||
|
|||
<DockPanel DockPanel.Dock="Bottom" Margin="0,12,0,0" Height="140"> |
|||
<DockPanel DockPanel.Dock="Top" Margin="0,0,0,4"> |
|||
<TextBlock Text="Operation Log" FontSize="13" FontWeight="SemiBold" |
|||
VerticalAlignment="Center" /> |
|||
<Button x:Name="ClearLogButton" Content="Clear" FontSize="11" |
|||
Padding="8,2" HorizontalAlignment="Right" Click="OnClearLog" /> |
|||
</DockPanel> |
|||
<Border BorderBrush="{DynamicResource SystemControlForegroundBaseMediumLowBrush}" |
|||
BorderThickness="1" CornerRadius="4" ClipToBounds="True"> |
|||
<ScrollViewer x:Name="LogScrollViewer"> |
|||
<StackPanel x:Name="LogPanel" Spacing="0" /> |
|||
</ScrollViewer> |
|||
</Border> |
|||
</DockPanel> |
|||
|
|||
<Border BorderBrush="{DynamicResource SystemControlForegroundBaseMediumLowBrush}" |
|||
BorderThickness="1" CornerRadius="8" ClipToBounds="True"> |
|||
<NavigationPage x:Name="NavPage"> |
|||
<NavigationPage.Resources> |
|||
<SolidColorBrush x:Key="NavigationBarBackground" Color="Transparent" /> |
|||
</NavigationPage.Resources> |
|||
</NavigationPage> |
|||
</Border> |
|||
</DockPanel> |
|||
|
|||
<!-- Right: dashboard --> |
|||
<Border Grid.Column="1" |
|||
BorderBrush="{DynamicResource SystemControlForegroundBaseMediumLowBrush}" |
|||
BorderThickness="1,0,0,0" |
|||
Padding="16"> |
|||
<ScrollViewer> |
|||
<StackPanel Spacing="12"> |
|||
|
|||
<TextBlock Text="Metrics" FontSize="16" FontWeight="SemiBold" |
|||
Foreground="{DynamicResource SystemControlHighlightAccentBrush}" /> |
|||
|
|||
<TextBlock x:Name="StackDepthText" Text="Stack Depth: 0" FontSize="13" /> |
|||
<TextBlock x:Name="LiveInstancesText" Text="Live Page Instances: 0" FontSize="13" /> |
|||
<TextBlock x:Name="TotalCreatedText" Text="Total Pages Created: 0" FontSize="13" /> |
|||
<DockPanel> |
|||
<TextBlock x:Name="ManagedMemoryText" Text="Managed Heap: 0.0 MB" FontSize="13" /> |
|||
<TextBlock x:Name="MemoryDeltaText" Text="" FontSize="13" |
|||
FontWeight="SemiBold" Margin="6,0,0,0" /> |
|||
</DockPanel> |
|||
|
|||
<Separator Margin="0,4" /> |
|||
|
|||
<TextBlock Text="Content Weight" FontSize="16" FontWeight="SemiBold" |
|||
Foreground="{DynamicResource SystemControlHighlightAccentBrush}" /> |
|||
|
|||
<ComboBox x:Name="WeightCombo" HorizontalAlignment="Stretch" SelectedIndex="0"> |
|||
<ComboBoxItem Content="Lightweight (~50 KB)" /> |
|||
<ComboBoxItem Content="Moderate (~500 KB)" /> |
|||
<ComboBoxItem Content="Heavy (~2 MB)" /> |
|||
</ComboBox> |
|||
<TextBlock Text="Sets the memory allocated by each new page. Push pages, pop them, then Force GC to see the heap drop." |
|||
TextWrapping="Wrap" FontSize="11" Opacity="0.6" /> |
|||
|
|||
<Separator Margin="0,4" /> |
|||
|
|||
<TextBlock Text="Actions" FontSize="16" FontWeight="SemiBold" |
|||
Foreground="{DynamicResource SystemControlHighlightAccentBrush}" /> |
|||
|
|||
<Button x:Name="PushButton" Content="Push Page" HorizontalAlignment="Stretch" Click="OnPush" /> |
|||
<Button x:Name="Push5Button" Content="Push 5 Pages" HorizontalAlignment="Stretch" Click="OnPush5" /> |
|||
<Button x:Name="PopButton" Content="Pop Page" HorizontalAlignment="Stretch" Click="OnPop" /> |
|||
<Button x:Name="PopToRootButton" Content="Pop to Root" HorizontalAlignment="Stretch" Click="OnPopToRoot" /> |
|||
|
|||
<Separator Margin="0,4" /> |
|||
|
|||
<Button x:Name="ForceGCButton" Content="Force GC + Refresh" |
|||
HorizontalAlignment="Stretch" Click="OnForceGC" |
|||
Background="{DynamicResource SystemControlHighlightAccentBrush}" |
|||
Foreground="White" /> |
|||
|
|||
<CheckBox x:Name="AutoRefreshCheck" Content="Auto-refresh (2s)" |
|||
FontSize="13" IsCheckedChanged="OnAutoRefreshChanged" /> |
|||
|
|||
<Separator Margin="0,4" /> |
|||
|
|||
<TextBlock Text="Stack" FontSize="16" FontWeight="SemiBold" |
|||
Foreground="{DynamicResource SystemControlHighlightAccentBrush}" /> |
|||
|
|||
<TextBlock Text="▲ Current (top)" FontSize="11" Opacity="0.45" Margin="0,-4,0,0" /> |
|||
<StackPanel x:Name="StackVisPanel" Spacing="4" /> |
|||
<TextBlock Text="▼ Root (bottom)" FontSize="11" Opacity="0.45" Margin="0,4,0,0" /> |
|||
|
|||
</StackPanel> |
|||
</ScrollViewer> |
|||
</Border> |
|||
|
|||
</Grid> |
|||
</UserControl> |
|||
@ -0,0 +1,125 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using Avalonia.Controls; |
|||
using Avalonia.Interactivity; |
|||
|
|||
namespace ControlCatalog.Pages |
|||
{ |
|||
public partial class ContentPagePerformancePage : UserControl |
|||
{ |
|||
private static readonly int[] AllocationSizes = [51_200, 512_000, 2_097_152]; |
|||
|
|||
private readonly NavigationPerformanceMonitorHelper _perf = new(); |
|||
private int _pageCounter; |
|||
|
|||
private readonly List<(Border Container, Border Badge, TextBlock IndexText, |
|||
TextBlock TitleText, TextBlock BadgeText)> _stackRowCache = new(); |
|||
|
|||
public ContentPagePerformancePage() |
|||
{ |
|||
InitializeComponent(); |
|||
} |
|||
|
|||
protected override async void OnLoaded(RoutedEventArgs e) |
|||
{ |
|||
base.OnLoaded(e); |
|||
|
|||
NavPage.Pushed += OnStackChanged; |
|||
NavPage.Popped += OnStackChanged; |
|||
NavPage.PoppedToRoot += OnStackChanged; |
|||
|
|||
_perf.InitHeap(); |
|||
_pageCounter++; |
|||
await NavPage.PushAsync(BuildPage("Home", _pageCounter)); |
|||
Log("Init", "Pushed root page"); |
|||
} |
|||
|
|||
protected override void OnUnloaded(RoutedEventArgs e) |
|||
{ |
|||
base.OnUnloaded(e); |
|||
_perf.StopAutoRefresh(); |
|||
} |
|||
|
|||
private void OnStackChanged(object? sender, NavigationEventArgs e) => RefreshAll(); |
|||
|
|||
private async void OnPush(object? sender, RoutedEventArgs e) |
|||
{ |
|||
_pageCounter++; |
|||
var page = BuildPage($"Page {_pageCounter}", _pageCounter); |
|||
await NavPage.PushAsync(page); |
|||
Log("Push", $"Pushed \"{page.Header}\""); |
|||
} |
|||
|
|||
private async void OnPush5(object? sender, RoutedEventArgs e) |
|||
{ |
|||
int first = _pageCounter + 1; |
|||
for (int i = 0; i < 5; i++) |
|||
{ |
|||
_pageCounter++; |
|||
await NavPage.PushAsync(BuildPage($"Page {_pageCounter}", _pageCounter)); |
|||
} |
|||
Log("Push ×5", $"Pushed pages {first}–{_pageCounter}"); |
|||
} |
|||
|
|||
private async void OnPop(object? sender, RoutedEventArgs e) |
|||
{ |
|||
if (NavPage.StackDepth > 1) |
|||
{ |
|||
var popped = NavPage.CurrentPage; |
|||
await NavPage.PopAsync(); |
|||
Log("Pop", $"Popped \"{popped?.Header}\""); |
|||
} |
|||
} |
|||
|
|||
private async void OnPopToRoot(object? sender, RoutedEventArgs e) |
|||
{ |
|||
if (NavPage.StackDepth > 1) |
|||
{ |
|||
int removed = NavPage.StackDepth - 1; |
|||
await NavPage.PopToRootAsync(); |
|||
Log("PopToRoot", $"Removed {removed} page(s)"); |
|||
} |
|||
} |
|||
|
|||
private void OnForceGC(object? sender, RoutedEventArgs e) |
|||
{ |
|||
_perf.ForceGC(RefreshAll); |
|||
Log("GC", "Forced full garbage collection"); |
|||
} |
|||
|
|||
private void OnClearLog(object? sender, RoutedEventArgs e) => LogPanel.Children.Clear(); |
|||
|
|||
private void OnAutoRefreshChanged(object? sender, RoutedEventArgs e) => |
|||
_perf.OnAutoRefreshChanged(AutoRefreshCheck, RefreshAll); |
|||
|
|||
private void RefreshAll() |
|||
{ |
|||
StackDepthText.Text = $"Stack Depth: {NavPage.StackDepth}"; |
|||
LiveInstancesText.Text = $"Live Page Instances: {_perf.CountLiveInstances()}"; |
|||
TotalCreatedText.Text = $"Total Pages Created: {_perf.TotalCreated}"; |
|||
_perf.UpdateHeapDelta(ManagedMemoryText, MemoryDeltaText); |
|||
|
|||
NavigationPerformanceMonitorHelper.RefreshStackPanel( |
|||
StackVisPanel, _stackRowCache, |
|||
NavPage.NavigationStack, NavPage.CurrentPage); |
|||
} |
|||
|
|||
private void Log(string action, string detail) => |
|||
_perf.LogOperation(action, detail, LogPanel, LogScrollViewer, |
|||
$"depth {NavPage.StackDepth}"); |
|||
|
|||
private ContentPage BuildPage(string title, int index) |
|||
{ |
|||
var weightIndex = WeightCombo.SelectedIndex >= 0 ? WeightCombo.SelectedIndex : 0; |
|||
var allocBytes = AllocationSizes[Math.Clamp(weightIndex, 0, AllocationSizes.Length - 1)]; |
|||
var weightLabel = weightIndex switch { 1 => "~500 KB", 2 => "~2 MB", _ => "~50 KB" }; |
|||
|
|||
var page = NavigationDemoHelper.MakePage(title, $"Stack position #{index} · Weight: {weightLabel}\n\n" + |
|||
"Pop this page and force GC to see the heap drop by the weight shown above. " + |
|||
"Live Instances decreases once the GC finalizes the page.", index); |
|||
page.Tag = new byte[allocBytes]; |
|||
_perf.TrackPage(page); |
|||
return page; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,171 @@ |
|||
<UserControl xmlns="https://github.com/avaloniaui" |
|||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
|||
x:Class="ControlCatalog.Pages.ContentPageSafeAreaPage"> |
|||
<DockPanel> |
|||
<ScrollViewer DockPanel.Dock="Right" Width="260"> |
|||
<StackPanel Margin="12" Spacing="8"> |
|||
<TextBlock Text="Configuration" FontWeight="SemiBold" FontSize="16" |
|||
Foreground="{DynamicResource SystemControlHighlightAccentBrush}" /> |
|||
|
|||
<CheckBox x:Name="AutoApplyCheck" |
|||
Content="AutomaticallyApplySafeAreaPadding" |
|||
IsChecked="True" |
|||
IsCheckedChanged="OnAutoApplyChanged" /> |
|||
|
|||
<TextBlock TextWrapping="Wrap" FontSize="12" Opacity="0.7"> |
|||
When enabled, ContentPage absorbs SafeAreaPadding into the content |
|||
presenter, keeping page content in the visible area. Set to false |
|||
to manage insets manually. |
|||
</TextBlock> |
|||
|
|||
<Separator /> |
|||
|
|||
<TextBlock Text="Simulated Insets" FontWeight="SemiBold" FontSize="13" /> |
|||
|
|||
<TextBlock Text="Top" FontSize="12" Opacity="0.8" /> |
|||
<DockPanel> |
|||
<TextBlock x:Name="TopValue" |
|||
DockPanel.Dock="Right" |
|||
Text="44" |
|||
FontSize="12" Opacity="0.6" |
|||
VerticalAlignment="Center" |
|||
Width="28" TextAlignment="Right" /> |
|||
<Slider x:Name="TopSlider" |
|||
Minimum="0" Maximum="80" Value="44" |
|||
TickFrequency="1" |
|||
ValueChanged="OnInsetChanged" /> |
|||
</DockPanel> |
|||
|
|||
<TextBlock Text="Bottom" FontSize="12" Opacity="0.8" /> |
|||
<DockPanel> |
|||
<TextBlock x:Name="BottomValue" |
|||
DockPanel.Dock="Right" |
|||
Text="34" |
|||
FontSize="12" Opacity="0.6" |
|||
VerticalAlignment="Center" |
|||
Width="28" TextAlignment="Right" /> |
|||
<Slider x:Name="BottomSlider" |
|||
Minimum="0" Maximum="60" Value="34" |
|||
TickFrequency="1" |
|||
ValueChanged="OnInsetChanged" /> |
|||
</DockPanel> |
|||
|
|||
<TextBlock Text="Left" FontSize="12" Opacity="0.8" /> |
|||
<DockPanel> |
|||
<TextBlock x:Name="LeftValue" |
|||
DockPanel.Dock="Right" |
|||
Text="0" |
|||
FontSize="12" Opacity="0.6" |
|||
VerticalAlignment="Center" |
|||
Width="28" TextAlignment="Right" /> |
|||
<Slider x:Name="LeftSlider" |
|||
Minimum="0" Maximum="60" Value="0" |
|||
TickFrequency="1" |
|||
ValueChanged="OnInsetChanged" /> |
|||
</DockPanel> |
|||
|
|||
<TextBlock Text="Right" FontSize="12" Opacity="0.8" /> |
|||
<DockPanel> |
|||
<TextBlock x:Name="RightValue" |
|||
DockPanel.Dock="Right" |
|||
Text="0" |
|||
FontSize="12" Opacity="0.6" |
|||
VerticalAlignment="Center" |
|||
Width="28" TextAlignment="Right" /> |
|||
<Slider x:Name="RightSlider" |
|||
Minimum="0" Maximum="60" Value="0" |
|||
TickFrequency="1" |
|||
ValueChanged="OnInsetChanged" /> |
|||
</DockPanel> |
|||
|
|||
<Separator /> |
|||
|
|||
<TextBlock Text="About" FontWeight="SemiBold" FontSize="13" /> |
|||
<StackPanel Spacing="4"> |
|||
<TextBlock TextWrapping="Wrap" FontSize="12" Opacity="0.8"> |
|||
• On real devices SafeAreaPadding is set by PageNavigationHost |
|||
from IInsetsManager (iOS, Android). |
|||
</TextBlock> |
|||
<TextBlock TextWrapping="Wrap" FontSize="12" Opacity="0.8"> |
|||
• ContentPage.AutomaticallyApplySafeAreaPadding defaults to true. |
|||
Set to false when your layout manages insets manually. |
|||
</TextBlock> |
|||
<TextBlock TextWrapping="Wrap" FontSize="12" Opacity="0.8"> |
|||
• Child pages inside a ContentPage receive the remaining insets |
|||
via SafeAreaPadding propagation. |
|||
</TextBlock> |
|||
</StackPanel> |
|||
</StackPanel> |
|||
</ScrollViewer> |
|||
|
|||
<Border DockPanel.Dock="Right" Width="1" Background="{DynamicResource SystemControlForegroundBaseMediumLowBrush}" /> |
|||
|
|||
<Border Margin="12" |
|||
BorderBrush="{DynamicResource SystemControlForegroundBaseMediumLowBrush}" |
|||
BorderThickness="1" |
|||
CornerRadius="12" |
|||
ClipToBounds="True" |
|||
MaxWidth="320" |
|||
HorizontalAlignment="Center"> |
|||
<Panel> |
|||
<ContentPage x:Name="SamplePage" |
|||
Header="Safe Area Demo" |
|||
HorizontalContentAlignment="Stretch" |
|||
VerticalContentAlignment="Stretch"> |
|||
<Grid RowDefinitions="Auto,*"> |
|||
<Border Grid.Row="0" |
|||
Background="{DynamicResource SystemControlBackgroundChromeMediumBrush}" |
|||
Padding="12,8"> |
|||
<StackPanel Spacing="2"> |
|||
<TextBlock x:Name="SafeAreaInfo" |
|||
FontSize="11" FontFamily="Consolas,Courier New,monospace" |
|||
Opacity="0.8" /> |
|||
<TextBlock x:Name="AutoApplyInfo" |
|||
FontSize="11" Opacity="0.8" /> |
|||
</StackPanel> |
|||
</Border> |
|||
|
|||
<StackPanel Grid.Row="1" |
|||
HorizontalAlignment="Center" |
|||
VerticalAlignment="Center" |
|||
Spacing="8"> |
|||
<TextBlock Text="Page Content" |
|||
FontSize="18" FontWeight="Bold" |
|||
HorizontalAlignment="Center" /> |
|||
<TextBlock TextWrapping="Wrap" |
|||
TextAlignment="Center" |
|||
FontSize="12" Opacity="0.6"> |
|||
When enabled, the content presenter absorbs the inset, |
|||
keeping content visible above the status bar and home indicator. |
|||
</TextBlock> |
|||
</StackPanel> |
|||
</Grid> |
|||
</ContentPage> |
|||
|
|||
<!-- Pink overlays to simulate device insets --> |
|||
<Border x:Name="TopInsetIndicator" |
|||
Background="#FF5252" Opacity="0.35" |
|||
VerticalAlignment="Top"> |
|||
<TextBlock Text="Safe Area (simulated)" |
|||
FontSize="10" Opacity="0.9" |
|||
HorizontalAlignment="Center" VerticalAlignment="Center" |
|||
Margin="0,4" /> |
|||
</Border> |
|||
<Border x:Name="BottomInsetIndicator" |
|||
Background="#FF5252" Opacity="0.35" |
|||
VerticalAlignment="Bottom"> |
|||
<TextBlock Text="Safe Area (simulated)" |
|||
FontSize="10" Opacity="0.9" |
|||
HorizontalAlignment="Center" VerticalAlignment="Center" |
|||
Margin="0,4" /> |
|||
</Border> |
|||
<Border x:Name="LeftInsetIndicator" |
|||
Background="#FF5252" Opacity="0.35" |
|||
HorizontalAlignment="Left" /> |
|||
<Border x:Name="RightInsetIndicator" |
|||
Background="#FF5252" Opacity="0.35" |
|||
HorizontalAlignment="Right" /> |
|||
</Panel> |
|||
</Border> |
|||
</DockPanel> |
|||
</UserControl> |
|||
@ -0,0 +1,70 @@ |
|||
using Avalonia; |
|||
using Avalonia.Controls; |
|||
using Avalonia.Controls.Primitives; |
|||
using Avalonia.Interactivity; |
|||
|
|||
namespace ControlCatalog.Pages |
|||
{ |
|||
public partial class ContentPageSafeAreaPage : UserControl |
|||
{ |
|||
public ContentPageSafeAreaPage() |
|||
{ |
|||
InitializeComponent(); |
|||
Loaded += OnLoaded; |
|||
} |
|||
|
|||
private void OnLoaded(object? sender, RoutedEventArgs e) |
|||
{ |
|||
SyncIndicators(); |
|||
} |
|||
|
|||
private void OnAutoApplyChanged(object? sender, RoutedEventArgs e) |
|||
{ |
|||
if (SamplePage == null) |
|||
return; |
|||
SamplePage.AutomaticallyApplySafeAreaPadding = AutoApplyCheck.IsChecked == true; |
|||
SyncIndicators(); |
|||
} |
|||
|
|||
private void OnInsetChanged(object? sender, RangeBaseValueChangedEventArgs e) |
|||
{ |
|||
SyncIndicators(); |
|||
} |
|||
|
|||
private void SyncIndicators() |
|||
{ |
|||
if (SamplePage == null) |
|||
return; |
|||
var top = (int)TopSlider.Value; |
|||
var bottom = (int)BottomSlider.Value; |
|||
var left = (int)LeftSlider.Value; |
|||
var right = (int)RightSlider.Value; |
|||
|
|||
TopValue.Text = $"{top}"; |
|||
BottomValue.Text = $"{bottom}"; |
|||
LeftValue.Text = $"{left}"; |
|||
RightValue.Text = $"{right}"; |
|||
|
|||
TopInsetIndicator.IsVisible = top > 0; |
|||
TopInsetIndicator.Height = top; |
|||
|
|||
BottomInsetIndicator.IsVisible = bottom > 0; |
|||
BottomInsetIndicator.Height = bottom; |
|||
|
|||
LeftInsetIndicator.IsVisible = left > 0; |
|||
LeftInsetIndicator.Width = left; |
|||
LeftInsetIndicator.Margin = new Thickness(0, top, 0, bottom); |
|||
|
|||
RightInsetIndicator.IsVisible = right > 0; |
|||
RightInsetIndicator.Width = right; |
|||
RightInsetIndicator.Margin = new Thickness(0, top, 0, bottom); |
|||
|
|||
var insets = new Thickness(left, top, right, bottom); |
|||
SamplePage.SafeAreaPadding = insets; |
|||
|
|||
SafeAreaInfo.Text = $"SafeAreaPadding: L={left} T={top} R={right} B={bottom}"; |
|||
AutoApplyInfo.Text = $"AutoApply: {SamplePage.AutomaticallyApplySafeAreaPadding} → " + |
|||
(SamplePage.AutomaticallyApplySafeAreaPadding ? "insets absorbed by presenter" : "insets ignored"); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,11 @@ |
|||
<UserControl xmlns="https://github.com/avaloniaui" |
|||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
|||
x:Class="ControlCatalog.Pages.DrawerDemoPage"> |
|||
<NavigationPage x:Name="SampleNav"> |
|||
<NavigationPage.Styles> |
|||
<Style Selector="NavigationPage#SampleNav /template/ Border#PART_NavigationBar"> |
|||
<Setter Property="Background" Value="Transparent" /> |
|||
</Style> |
|||
</NavigationPage.Styles> |
|||
</NavigationPage> |
|||
</UserControl> |
|||
@ -0,0 +1,73 @@ |
|||
using System; |
|||
using Avalonia.Controls; |
|||
using Avalonia.Interactivity; |
|||
|
|||
namespace ControlCatalog.Pages |
|||
{ |
|||
public partial class DrawerDemoPage : UserControl |
|||
{ |
|||
private static readonly (string Group, string Title, string Description, Func<UserControl> Factory)[] Demos = |
|||
{ |
|||
// Overview
|
|||
("Overview", "First Look", "Basic DrawerPage with a navigation drawer, menu items, and detail content.", |
|||
() => new DrawerPageFirstLookPage()), |
|||
|
|||
// Features
|
|||
("Features", "Navigation", |
|||
"Master-detail pattern: select a drawer menu item to navigate the detail via a NavigationPage with hamburger-to-back-button transition.", |
|||
() => new DrawerPageNavigationPage()), |
|||
("Features", "Compact Rail", |
|||
"CompactOverlay and CompactInline layout modes: a narrow icon rail is always visible and expands on open. Adjust rail width and open pane width.", |
|||
() => new DrawerPageCompactPage()), |
|||
("Features", "Events", |
|||
"Opened, Closing, and Closed drawer events plus NavigatedTo and NavigatedFrom page lifecycle events. Enable 'Cancel next close' to prevent the drawer from closing.", |
|||
() => new DrawerPageEventsPage()), |
|||
("Features", "RTL Layout", "Right-to-left layout: drawer opens from the right edge with mirrored gestures.", |
|||
() => new DrawerPageRtlPage()), |
|||
|
|||
// Appearance
|
|||
("Appearance", "Customization", |
|||
"Customize drawer behavior, layout mode, length, colors, header and footer.", |
|||
() => new DrawerPageCustomizationPage()), |
|||
("Appearance", "Custom Flyout", |
|||
"Dark overlay menu with staggered item animations and CrossFade page transitions on the detail NavigationPage.", |
|||
() => new DrawerPageCustomFlyoutPage()), |
|||
("Appearance", "Transitions", |
|||
"Configure the detail NavigationPage transition. Choose CrossFade, PageSlide, or CompositePageTransition to animate detail page changes.", |
|||
() => new DrawerPageTransitionsPage()), |
|||
|
|||
// Performance
|
|||
("Performance", "Performance Monitor", |
|||
"Track detail page swaps, live page instances, and managed heap size. Observe how GC reclaims memory after swapping pages.", |
|||
() => new DrawerPagePerformancePage()), |
|||
|
|||
// Showcases
|
|||
("Showcases", "AvaloniaFlix", |
|||
"Streaming app with DrawerPage wrapping NavigationPage. Hamburger auto-injected at root, back arrow on detail, and dark themed flyout menu.", |
|||
() => new AvaloniaFlixAppPage()), |
|||
("Showcases", "L'Avenir Restaurant", |
|||
"Restaurant app with DrawerPage as the root container, NavigationPage for detail navigation, and TabbedPage bottom tabs for Menu, Reservations, and Profile.", |
|||
() => new LAvenirAppPage()), |
|||
("Showcases", "EcoTracker", |
|||
"Sustainability tracker with CompactInline drawer, eco leaf hamburger icon, crossfade compact/open menu transitions, and green-themed Home, Stats, Habits, and Community pages.", |
|||
() => new EcoTrackerAppPage()), |
|||
("Showcases", "ModernApp", |
|||
"Travel social app using a top-placement DrawerPage. A slide-down nav pane gives access to Discover, My Trips, Profile, and Settings. Features destination cards, story circles, an experience feed, a stats profile, and a travel gallery.", |
|||
() => new ModernAppPage()), |
|||
("Showcases", "Controls Gallery App", |
|||
"Controls gallery app using DrawerPage CompactInline mode. Dark Fluent palette, accent pill selection indicator, search box that fades in when open, expandable category groups, and Settings pinned to the footer.", |
|||
() => new ControlsGalleryAppPage()), |
|||
}; |
|||
|
|||
public DrawerDemoPage() |
|||
{ |
|||
InitializeComponent(); |
|||
Loaded += OnLoaded; |
|||
} |
|||
|
|||
private async void OnLoaded(object? sender, RoutedEventArgs e) |
|||
{ |
|||
await SampleNav.PushAsync(NavigationDemoHelper.CreateGalleryHomePage(SampleNav, Demos), null); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,400 @@ |
|||
<UserControl xmlns="https://github.com/avaloniaui" |
|||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
|||
x:Class="ControlCatalog.Pages.ControlsGalleryAppPage"> |
|||
|
|||
<UserControl.Resources> |
|||
<SolidColorBrush x:Key="NavPaneBg" Color="#202020"/> |
|||
<SolidColorBrush x:Key="NavContentBg" Color="#141414"/> |
|||
<SolidColorBrush x:Key="NavItemHover" Color="#1AFFFFFF"/> |
|||
<SolidColorBrush x:Key="NavItemSelected" Color="#0FFFFFFF"/> |
|||
<SolidColorBrush x:Key="NavAccent" Color="#60CDFF"/> |
|||
<SolidColorBrush x:Key="NavText" Color="#FFFFFF"/> |
|||
<SolidColorBrush x:Key="NavTextSecondary" Color="#C8FFFFFF"/> |
|||
<SolidColorBrush x:Key="NavBorder" Color="#2EFFFFFF"/> |
|||
<SolidColorBrush x:Key="NavSearchBg" Color="#0BFFFFFF"/> |
|||
</UserControl.Resources> |
|||
|
|||
<DockPanel> |
|||
<ScrollViewer x:Name="InfoPanel" DockPanel.Dock="Right" Width="280"> |
|||
<StackPanel Margin="16" Spacing="12"> |
|||
<TextBlock Text="Controls Gallery App" FontSize="15" FontWeight="SemiBold" |
|||
Foreground="{DynamicResource SystemControlHighlightAccentBrush}" /> |
|||
<TextBlock TextWrapping="Wrap" FontSize="12" Opacity="0.7" |
|||
Text="Controls gallery app built with DrawerPage CompactInline mode. Dark Fluent palette, accent pill indicator, search box that fades in when open, expandable groups, and Settings pinned to the footer." /> |
|||
<Separator /> |
|||
<TextBlock Text="Layout" FontSize="13" FontWeight="SemiBold" /> |
|||
<StackPanel Spacing="4"> |
|||
<TextBlock FontSize="12" TextWrapping="Wrap" Text="• CompactInline — icon rail always visible" /> |
|||
<TextBlock FontSize="12" TextWrapping="Wrap" Text="• CompactDrawerLength = 48 (icon only)" /> |
|||
<TextBlock FontSize="12" TextWrapping="Wrap" Text="• DrawerLength = 280 (icon + label)" /> |
|||
<TextBlock FontSize="12" TextWrapping="Wrap" Text="• Left accent pill on selected item" /> |
|||
<TextBlock FontSize="12" TextWrapping="Wrap" Text="• Search box fades in when open" /> |
|||
<TextBlock FontSize="12" TextWrapping="Wrap" Text="• Settings pinned to drawer footer" /> |
|||
</StackPanel> |
|||
<Separator /> |
|||
<TextBlock Text="Key Code" FontSize="13" FontWeight="SemiBold" /> |
|||
<Border Background="{DynamicResource SystemControlBackgroundBaseLowBrush}" |
|||
CornerRadius="4" Padding="8"> |
|||
<TextBlock FontFamily="Cascadia Code,Consolas,Menlo,monospace" |
|||
FontSize="10" TextWrapping="Wrap" |
|||
Text="<DrawerPage
 DrawerLayoutBehavior="CompactInline"
 CompactDrawerLength="48"
 DrawerLength="280"
 DrawerBackground="#202020">" /> |
|||
</Border> |
|||
</StackPanel> |
|||
</ScrollViewer> |
|||
|
|||
<Border BorderBrush="{DynamicResource SystemControlForegroundBaseMediumLowBrush}" |
|||
BorderThickness="1" CornerRadius="8" ClipToBounds="True"> |
|||
|
|||
<DrawerPage x:Name="NavDrawer" |
|||
DrawerLayoutBehavior="CompactInline" |
|||
CompactDrawerLength="48" |
|||
DrawerLength="280" |
|||
Background="{StaticResource NavContentBg}" |
|||
DrawerBackground="{StaticResource NavPaneBg}"> |
|||
|
|||
<!-- ── Drawer header: hamburger + app title ── --> |
|||
<DrawerPage.DrawerHeader> |
|||
<StackPanel Background="{StaticResource NavPaneBg}"> |
|||
|
|||
<!-- Hamburger row --> |
|||
<Button x:Name="BtnHamburger" Click="OnHamburgerClick" |
|||
Width="48" Height="40" Padding="0" Margin="0,8,0,0" |
|||
HorizontalAlignment="Left" |
|||
Background="Transparent" BorderThickness="0" |
|||
ToolTip.Tip="Navigation menu" |
|||
HorizontalContentAlignment="Center" VerticalContentAlignment="Center"> |
|||
<PathIcon Width="16" Height="16" |
|||
Foreground="{StaticResource NavText}" |
|||
Data="M3 18h18v-2H3v2zm0-5h18v-2H3v2zm0-7v2h18V6H3z" /> |
|||
</Button> |
|||
|
|||
<!-- Search box — fades in when drawer is open --> |
|||
<Border Margin="8,8,8,4" |
|||
Background="{StaticResource NavSearchBg}" |
|||
BorderBrush="{StaticResource NavBorder}" |
|||
BorderThickness="1" CornerRadius="4" Height="32" |
|||
Classes="openFade" |
|||
Classes.drawerOpen="{Binding #NavDrawer.IsOpen}"> |
|||
<Grid ColumnDefinitions="Auto,*" Margin="8,0"> |
|||
<PathIcon Grid.Column="0" Width="12" Height="12" |
|||
Foreground="{StaticResource NavTextSecondary}" |
|||
Data="M15.5 14h-.79l-.28-.27A6.471 6.471 0 0 0 16 9.5 6.5 6.5 0 1 0 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z" /> |
|||
<TextBox x:Name="SearchBox" Grid.Column="1" |
|||
PlaceholderText="Search" |
|||
Background="Transparent" BorderThickness="0" |
|||
Padding="6,0,0,0" |
|||
Foreground="{StaticResource NavText}" |
|||
PlaceholderForeground="{StaticResource NavTextSecondary}" |
|||
FontSize="12" |
|||
VerticalAlignment="Center" |
|||
VerticalContentAlignment="Center" |
|||
TextChanged="OnSearchTextChanged" /> |
|||
</Grid> |
|||
</Border> |
|||
|
|||
</StackPanel> |
|||
</DrawerPage.DrawerHeader> |
|||
|
|||
<!-- ── Nav items ── --> |
|||
<DrawerPage.Drawer> |
|||
<ContentPage Background="Transparent"> |
|||
<StackPanel Margin="0,4,0,0" Spacing="2"> |
|||
|
|||
<!-- What's New (selected) --> |
|||
<Button x:Name="BtnWhatsNew" Tag="WhatsNew" |
|||
Classes="navItem navItemSelected" |
|||
Click="OnNavItemClick" ToolTip.Tip="What's New"> |
|||
<Panel> |
|||
<Border Classes="navPill" Width="3" Height="16" CornerRadius="2" |
|||
Background="#60CDFF" HorizontalAlignment="Left" VerticalAlignment="Center" |
|||
Margin="4,0,0,0" /> |
|||
<StackPanel Orientation="Horizontal" VerticalAlignment="Center"> |
|||
<PathIcon Width="16" Height="16" Margin="16,0,0,0" |
|||
Foreground="{StaticResource NavText}" |
|||
Data="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 14.5v-9l6 4.5-6 4.5z" /> |
|||
<TextBlock Text="What's New" FontSize="13" Margin="12,0,0,0" |
|||
Foreground="{StaticResource NavText}" |
|||
VerticalAlignment="Center" |
|||
Classes="openFade" |
|||
Classes.drawerOpen="{Binding #NavDrawer.IsOpen}" /> |
|||
</StackPanel> |
|||
</Panel> |
|||
</Button> |
|||
|
|||
<!-- All Controls --> |
|||
<Button x:Name="BtnAllControls" Tag="AllControls" |
|||
Classes="navItem" |
|||
Click="OnNavItemClick" ToolTip.Tip="All Controls"> |
|||
<Panel> |
|||
<Border Classes="navPill" Width="3" Height="16" CornerRadius="2" |
|||
Background="#60CDFF" HorizontalAlignment="Left" VerticalAlignment="Center" |
|||
Margin="4,0,0,0" /> |
|||
<StackPanel Orientation="Horizontal" VerticalAlignment="Center"> |
|||
<PathIcon Width="16" Height="16" Margin="16,0,0,0" |
|||
Foreground="{StaticResource NavText}" |
|||
Data="M3 3h8v8H3V3m10 0h8v8h-8V3M3 13h8v8H3v-8m10 0h8v8h-8v-8" /> |
|||
<TextBlock Text="All Controls" FontSize="13" Margin="12,0,0,0" |
|||
Foreground="{StaticResource NavText}" |
|||
VerticalAlignment="Center" |
|||
Classes="openFade" |
|||
Classes.drawerOpen="{Binding #NavDrawer.IsOpen}" /> |
|||
</StackPanel> |
|||
</Panel> |
|||
</Button> |
|||
|
|||
<!-- Separator --> |
|||
<Border Height="1" Background="{StaticResource NavBorder}" Margin="8,4" /> |
|||
|
|||
<!-- Basic Input (expandable) --> |
|||
<Button x:Name="BtnBasicInput" Tag="BasicInput" |
|||
Classes="navItem" |
|||
Click="OnNavItemClick" ToolTip.Tip="Basic Input"> |
|||
<Panel> |
|||
<Border Classes="navPill" Width="3" Height="16" CornerRadius="2" |
|||
Background="#60CDFF" HorizontalAlignment="Left" VerticalAlignment="Center" |
|||
Margin="4,0,0,0" /> |
|||
<Grid ColumnDefinitions="Auto,*" VerticalAlignment="Center"> |
|||
<PathIcon Grid.Column="0" Width="16" Height="16" Margin="16,0,0,0" |
|||
Foreground="{StaticResource NavText}" |
|||
Data="M9 11H7v2h2v-2zm4 0h-2v2h2v-2zm4 0h-2v2h2v-2zm2-7h-1V2h-2v2H8V2H6v2H5c-1.11 0-1.99.9-1.99 2L3 20c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm0 16H5V9h14v11z" /> |
|||
<TextBlock Grid.Column="1" Text="Basic Input" FontSize="13" Margin="12,0,0,0" |
|||
Foreground="{StaticResource NavText}" |
|||
VerticalAlignment="Center" |
|||
Classes="openFade" |
|||
Classes.drawerOpen="{Binding #NavDrawer.IsOpen}" /> |
|||
</Grid> |
|||
</Panel> |
|||
</Button> |
|||
|
|||
<!-- Collections --> |
|||
<Button x:Name="BtnCollections" Tag="Collections" |
|||
Classes="navItem" |
|||
Click="OnNavItemClick" ToolTip.Tip="Collections"> |
|||
<Panel> |
|||
<Border Classes="navPill" Width="3" Height="16" CornerRadius="2" |
|||
Background="#60CDFF" HorizontalAlignment="Left" VerticalAlignment="Center" |
|||
Margin="4,0,0,0" /> |
|||
<Grid ColumnDefinitions="Auto,*" VerticalAlignment="Center"> |
|||
<PathIcon Grid.Column="0" Width="16" Height="16" Margin="16,0,0,0" |
|||
Foreground="{StaticResource NavText}" |
|||
Data="M4 6H2v14c0 1.1.9 2 2 2h14v-2H4V6zm16-4H8c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm-1 9H9V9h10v2zm-4 4H9v-2h6v2zm4-8H9V5h10v2z" /> |
|||
<TextBlock Grid.Column="1" Text="Collections" FontSize="13" Margin="12,0,0,0" |
|||
Foreground="{StaticResource NavText}" |
|||
VerticalAlignment="Center" |
|||
Classes="openFade" |
|||
Classes.drawerOpen="{Binding #NavDrawer.IsOpen}" /> |
|||
</Grid> |
|||
</Panel> |
|||
</Button> |
|||
|
|||
<!-- Media --> |
|||
<Button x:Name="BtnMedia" Tag="Media" |
|||
Classes="navItem" |
|||
Click="OnNavItemClick" ToolTip.Tip="Media"> |
|||
<Panel> |
|||
<Border Classes="navPill" Width="3" Height="16" CornerRadius="2" |
|||
Background="#60CDFF" HorizontalAlignment="Left" VerticalAlignment="Center" |
|||
Margin="4,0,0,0" /> |
|||
<Grid ColumnDefinitions="Auto,*" VerticalAlignment="Center"> |
|||
<PathIcon Grid.Column="0" Width="16" Height="16" Margin="16,0,0,0" |
|||
Foreground="{StaticResource NavText}" |
|||
Data="M21 3H3C2 3 1 4 1 5v14c0 1.1.9 2 2 2h18c1.1 0 2-.9 2-2V5c0-1-1-2-2-2zm0 16H3V5h18v14zM8 15c0 1.66 1.34 3 3 3s3-1.34 3-3V9h3V7h-5v8c0 .55-.45 1-1 1s-1-.45-1-1V7H8v8z" /> |
|||
<TextBlock Grid.Column="1" Text="Media" FontSize="13" Margin="12,0,0,0" |
|||
Foreground="{StaticResource NavText}" |
|||
VerticalAlignment="Center" |
|||
Classes="openFade" |
|||
Classes.drawerOpen="{Binding #NavDrawer.IsOpen}" /> |
|||
</Grid> |
|||
</Panel> |
|||
</Button> |
|||
|
|||
<!-- Menus and Toolbars --> |
|||
<Button x:Name="BtnMenus" Tag="Menus" |
|||
Classes="navItem" |
|||
Click="OnNavItemClick" ToolTip.Tip="Menus and Toolbars"> |
|||
<Panel> |
|||
<Border Classes="navPill" Width="3" Height="16" CornerRadius="2" |
|||
Background="#60CDFF" HorizontalAlignment="Left" VerticalAlignment="Center" |
|||
Margin="4,0,0,0" /> |
|||
<Grid ColumnDefinitions="Auto,*" VerticalAlignment="Center"> |
|||
<PathIcon Grid.Column="0" Width="16" Height="16" Margin="16,0,0,0" |
|||
Foreground="{StaticResource NavText}" |
|||
Data="M3 18h18v-2H3v2zm0-5h18v-2H3v2zm0-7v2h18V6H3z" /> |
|||
<TextBlock Grid.Column="1" Text="Menus and Toolbars" FontSize="13" Margin="12,0,0,0" |
|||
Foreground="{StaticResource NavText}" |
|||
VerticalAlignment="Center" |
|||
Classes="openFade" |
|||
Classes.drawerOpen="{Binding #NavDrawer.IsOpen}" /> |
|||
</Grid> |
|||
</Panel> |
|||
</Button> |
|||
|
|||
<!-- Navigation --> |
|||
<Button x:Name="BtnNavigation" Tag="Navigation" |
|||
Classes="navItem" |
|||
Click="OnNavItemClick" ToolTip.Tip="Navigation"> |
|||
<Panel> |
|||
<Border Classes="navPill" Width="3" Height="16" CornerRadius="2" |
|||
Background="#60CDFF" HorizontalAlignment="Left" VerticalAlignment="Center" |
|||
Margin="4,0,0,0" /> |
|||
<Grid ColumnDefinitions="Auto,*" VerticalAlignment="Center"> |
|||
<PathIcon Grid.Column="0" Width="16" Height="16" Margin="16,0,0,0" |
|||
Foreground="{StaticResource NavText}" |
|||
Data="M12 2L4.5 20.29l.71.71L12 18l6.79 3 .71-.71z" /> |
|||
<TextBlock Grid.Column="1" Text="Navigation" FontSize="13" Margin="12,0,0,0" |
|||
Foreground="{StaticResource NavText}" |
|||
VerticalAlignment="Center" |
|||
Classes="openFade" |
|||
Classes.drawerOpen="{Binding #NavDrawer.IsOpen}" /> |
|||
</Grid> |
|||
</Panel> |
|||
</Button> |
|||
|
|||
<!-- Text --> |
|||
<Button x:Name="BtnText" Tag="Text" |
|||
Classes="navItem" |
|||
Click="OnNavItemClick" ToolTip.Tip="Text"> |
|||
<Panel> |
|||
<Border Classes="navPill" Width="3" Height="16" CornerRadius="2" |
|||
Background="#60CDFF" HorizontalAlignment="Left" VerticalAlignment="Center" |
|||
Margin="4,0,0,0" /> |
|||
<StackPanel Orientation="Horizontal" VerticalAlignment="Center"> |
|||
<PathIcon Width="16" Height="16" Margin="16,0,0,0" |
|||
Foreground="{StaticResource NavText}" |
|||
Data="M5 17v2h14v-2H5zm4.5-4.2h5l.9 2.2h2.1L12.75 4h-1.5L6.5 15h2.1l.9-2.2zM12 5.98L13.87 11h-3.74L12 5.98z" /> |
|||
<TextBlock Text="Text" FontSize="13" Margin="12,0,0,0" |
|||
Foreground="{StaticResource NavText}" |
|||
VerticalAlignment="Center" |
|||
Classes="openFade" |
|||
Classes.drawerOpen="{Binding #NavDrawer.IsOpen}" /> |
|||
</StackPanel> |
|||
</Panel> |
|||
</Button> |
|||
|
|||
</StackPanel> |
|||
</ContentPage> |
|||
</DrawerPage.Drawer> |
|||
|
|||
<!-- ── Settings pinned to footer ── --> |
|||
<DrawerPage.DrawerFooter> |
|||
<StackPanel Background="{StaticResource NavPaneBg}" Margin="0,0,0,4"> |
|||
<Border Height="1" Background="{StaticResource NavBorder}" Margin="4,0" /> |
|||
<Button x:Name="BtnSettings" Tag="Settings" |
|||
Classes="navItem" |
|||
Click="OnNavItemClick" ToolTip.Tip="Settings" |
|||
Margin="0,4,0,4"> |
|||
<Panel> |
|||
<Border Classes="navPill" Width="3" Height="16" CornerRadius="2" |
|||
Background="#60CDFF" HorizontalAlignment="Left" VerticalAlignment="Center" |
|||
Margin="4,0,0,0" /> |
|||
<StackPanel Orientation="Horizontal" VerticalAlignment="Center"> |
|||
<PathIcon Width="16" Height="16" Margin="16,0,0,0" |
|||
Foreground="{StaticResource NavText}" |
|||
Data="M19.14,12.94c0.04-0.3,0.06-0.61,0.06-0.94c0-0.32-0.02-0.64-0.07-0.94l2.03-1.58c0.18-0.14,0.23-0.41,0.12-0.61l-1.92-3.32c-0.12-0.22-0.37-0.29-0.59-0.22l-2.39,0.96c-0.5-0.38-1.03-0.7-1.62-0.94L14.4,2.81c-0.04-0.24-0.24-0.41-0.48-0.41h-3.84c-0.24,0-0.43,0.17-0.47,0.41L9.25,5.35C8.66,5.59,8.12,5.92,7.63,6.29L5.24,5.33c-0.22-0.08-0.47,0-0.59,0.22L2.74,8.87C2.62,9.08,2.66,9.34,2.86,9.48l2.03,1.58C4.84,11.36,4.8,11.69,4.8,12s0.02,0.64,0.07,0.94l-2.03,1.58c-0.18,0.14-0.23,0.41-0.12,0.61l1.92,3.32c0.12,0.22,0.37,0.29,0.59,0.22l2.39-0.96c0.5,0.38,1.03,0.7,1.62,0.94l0.36,2.54c0.05,0.24,0.24,0.41,0.48,0.41h3.84c0.24,0,0.44-0.17,0.47-0.41l0.36-2.54c0.59-0.24,1.13-0.56,1.62-0.94l2.39,0.96c0.22,0.08,0.47,0,0.59-0.22l1.92-3.32c0.12-0.22,0.07-0.47-0.12-0.61L19.14,12.94zM12,15.6c-1.98,0-3.6-1.62-3.6-3.6s1.62-3.6,3.6-3.6s3.6,1.62,3.6,3.6S13.98,15.6,12,15.6z" /> |
|||
<TextBlock Text="Settings" FontSize="13" Margin="12,0,0,0" |
|||
Foreground="{StaticResource NavText}" |
|||
VerticalAlignment="Center" |
|||
Classes="openFade" |
|||
Classes.drawerOpen="{Binding #NavDrawer.IsOpen}" /> |
|||
</StackPanel> |
|||
</Panel> |
|||
</Button> |
|||
</StackPanel> |
|||
</DrawerPage.DrawerFooter> |
|||
|
|||
<!-- ── Detail area — BarHeight=0 hides the navigation bar entirely ── --> |
|||
<DrawerPage.Content> |
|||
<NavigationPage x:Name="DetailNav" |
|||
Background="{StaticResource NavContentBg}" |
|||
BarHeight="0" /> |
|||
</DrawerPage.Content> |
|||
|
|||
</DrawerPage> |
|||
</Border> |
|||
</DockPanel> |
|||
|
|||
<UserControl.Styles> |
|||
|
|||
<!-- openFade: collapsed (removed from layout) when closed, visible when open --> |
|||
<Style Selector=":is(Control).openFade"> |
|||
<Setter Property="IsVisible" Value="False" /> |
|||
</Style> |
|||
<Style Selector=":is(Control).openFade.drawerOpen"> |
|||
<Setter Property="IsVisible" Value="True" /> |
|||
</Style> |
|||
|
|||
<!-- Hamburger button --> |
|||
<Style Selector="Button#BtnHamburger /template/ ContentPresenter#PART_ContentPresenter"> |
|||
<Setter Property="Background" Value="Transparent" /> |
|||
<Setter Property="CornerRadius" Value="4" /> |
|||
</Style> |
|||
<Style Selector="Button#BtnHamburger:pointerover /template/ ContentPresenter#PART_ContentPresenter"> |
|||
<Setter Property="Background" Value="#1AFFFFFF" /> |
|||
</Style> |
|||
<Style Selector="Button#BtnHamburger:pressed /template/ ContentPresenter#PART_ContentPresenter"> |
|||
<Setter Property="Background" Value="#2AFFFFFF" /> |
|||
</Style> |
|||
|
|||
<!-- Nav item base --> |
|||
<Style Selector="Button.navItem"> |
|||
<Setter Property="HorizontalAlignment" Value="Stretch" /> |
|||
<Setter Property="HorizontalContentAlignment" Value="Stretch" /> |
|||
<Setter Property="Height" Value="40" /> |
|||
<Setter Property="Padding" Value="0" /> |
|||
<Setter Property="CornerRadius" Value="4" /> |
|||
</Style> |
|||
<Style Selector="Button.navItem /template/ ContentPresenter#PART_ContentPresenter"> |
|||
<Setter Property="Background" Value="Transparent" /> |
|||
<Setter Property="Padding" Value="0" /> |
|||
</Style> |
|||
<Style Selector="Button.navItem:pointerover /template/ ContentPresenter#PART_ContentPresenter"> |
|||
<Setter Property="Background" Value="#1AFFFFFF" /> |
|||
</Style> |
|||
<Style Selector="Button.navItem:pressed /template/ ContentPresenter#PART_ContentPresenter"> |
|||
<Setter Property="Background" Value="#2AFFFFFF" /> |
|||
</Style> |
|||
|
|||
<!-- navPill: hidden by default, visible only on selected item --> |
|||
<Style Selector="Button.navItem Border.navPill"> |
|||
<Setter Property="IsVisible" Value="False" /> |
|||
</Style> |
|||
<Style Selector="Button.navItemSelected Border.navPill"> |
|||
<Setter Property="IsVisible" Value="True" /> |
|||
</Style> |
|||
|
|||
<!-- SearchBox: fully transparent, suppress all themed states --> |
|||
<Style Selector="TextBox#SearchBox"> |
|||
<Setter Property="MinHeight" Value="0" /> |
|||
<Setter Property="CaretBrush" Value="{StaticResource NavAccent}" /> |
|||
<Setter Property="SelectionBrush" Value="#4060CDFF" /> |
|||
</Style> |
|||
<Style Selector="TextBox#SearchBox /template/ Border#PART_BorderElement"> |
|||
<Setter Property="Background" Value="Transparent" /> |
|||
<Setter Property="BorderThickness" Value="0" /> |
|||
<Setter Property="MinHeight" Value="0" /> |
|||
</Style> |
|||
<Style Selector="TextBox#SearchBox:pointerover /template/ Border#PART_BorderElement"> |
|||
<Setter Property="Background" Value="Transparent" /> |
|||
<Setter Property="BorderThickness" Value="0" /> |
|||
</Style> |
|||
<Style Selector="TextBox#SearchBox:focus-within /template/ Border#PART_BorderElement"> |
|||
<Setter Property="Background" Value="Transparent" /> |
|||
<Setter Property="BorderBrush" Value="Transparent" /> |
|||
<Setter Property="BorderThickness" Value="0" /> |
|||
</Style> |
|||
<Style Selector="TextBox#SearchBox:error /template/ Border#PART_BorderElement"> |
|||
<Setter Property="Background" Value="Transparent" /> |
|||
<Setter Property="BorderThickness" Value="0" /> |
|||
</Style> |
|||
|
|||
<!-- Nav item selected state --> |
|||
<Style Selector="Button.navItemSelected /template/ ContentPresenter#PART_ContentPresenter"> |
|||
<Setter Property="Background" Value="#0FFFFFFF" /> |
|||
</Style> |
|||
<Style Selector="Button.navItemSelected:pointerover /template/ ContentPresenter#PART_ContentPresenter"> |
|||
<Setter Property="Background" Value="#1AFFFFFF" /> |
|||
</Style> |
|||
|
|||
</UserControl.Styles> |
|||
|
|||
</UserControl> |
|||
@ -0,0 +1,464 @@ |
|||
using System; |
|||
using Avalonia; |
|||
using Avalonia.Animation; |
|||
using Avalonia.Controls; |
|||
using Avalonia.Interactivity; |
|||
using Avalonia.Layout; |
|||
using Avalonia.Media; |
|||
|
|||
namespace ControlCatalog.Pages; |
|||
|
|||
public partial class ControlsGalleryAppPage : UserControl |
|||
{ |
|||
static readonly Color Accent = Color.Parse("#60CDFF"); |
|||
static readonly Color ContentBg = Color.Parse("#141414"); |
|||
static readonly Color CardBg = Color.Parse("#1F1F1F"); |
|||
static readonly Color BorderCol = Color.Parse("#2EFFFFFF"); |
|||
static readonly Color TextCol = Color.Parse("#FFFFFF"); |
|||
static readonly Color TextSec = Color.Parse("#C8FFFFFF"); |
|||
static readonly Color TextMuted = Color.Parse("#80FFFFFF"); |
|||
|
|||
DrawerPage? _drawer; |
|||
NavigationPage? _detailNav; |
|||
Button? _selectedBtn; |
|||
TextBox? _searchBox; |
|||
ContentPage? _preSearchPage; |
|||
bool _isSearching; |
|||
|
|||
public ControlsGalleryAppPage() |
|||
{ |
|||
InitializeComponent(); |
|||
|
|||
_drawer = this.FindControl<DrawerPage>("NavDrawer"); |
|||
_detailNav = this.FindControl<NavigationPage>("DetailNav"); |
|||
_selectedBtn = this.FindControl<Button>("BtnWhatsNew"); |
|||
_searchBox = this.FindControl<TextBox>("SearchBox"); |
|||
|
|||
if (_detailNav != null) |
|||
_ = _detailNav.PushAsync(BuildWhatsNewPage()); |
|||
} |
|||
|
|||
private void OnHamburgerClick(object? sender, RoutedEventArgs e) |
|||
{ |
|||
if (_drawer != null) |
|||
_drawer.IsOpen = !_drawer.IsOpen; |
|||
} |
|||
|
|||
private async void OnNavItemClick(object? sender, RoutedEventArgs e) |
|||
{ |
|||
if (sender is not Button btn || btn.Tag is not string tag) return; |
|||
if (btn == _selectedBtn) return; |
|||
|
|||
if (_selectedBtn != null) |
|||
_selectedBtn.Classes.Remove("navItemSelected"); |
|||
_selectedBtn = btn; |
|||
btn.Classes.Add("navItemSelected"); |
|||
|
|||
if (_detailNav == null) return; |
|||
|
|||
var page = tag switch |
|||
{ |
|||
"WhatsNew" => BuildWhatsNewPage(), |
|||
"AllControls" => BuildAllControlsPage(), |
|||
"BasicInput" => BuildCategoryPage("Basic Input", |
|||
"Buttons, checkboxes, radio buttons, sliders, and toggle switches."), |
|||
"Collections" => BuildCategoryPage("Collections", |
|||
"List view, tree view, data grid, flip view, and more."), |
|||
"Media" => BuildCategoryPage("Media", |
|||
"Image, web view, map control, and media player."), |
|||
"Menus" => BuildCategoryPage("Menus and Toolbars", |
|||
"Menus, context menus, command bar, and toolbar."), |
|||
"Navigation" => BuildCategoryPage("Navigation", |
|||
"Navigation view, pivot, tab control, and breadcrumb bar."), |
|||
"Text" => BuildCategoryPage("Text", |
|||
"Text block, text box, auto-suggest box, and rich text."), |
|||
"Settings" => BuildSettingsPage(), |
|||
_ => BuildWhatsNewPage(), |
|||
}; |
|||
|
|||
NavigationPage.SetHasBackButton(page, false); |
|||
await _detailNav.ReplaceAsync(page, new CrossFade(TimeSpan.FromMilliseconds(180))); |
|||
} |
|||
|
|||
private void OnSearchTextChanged(object? sender, TextChangedEventArgs e) |
|||
{ |
|||
if (_detailNav == null) return; |
|||
var query = _searchBox?.Text?.Trim() ?? ""; |
|||
|
|||
if (query.Length == 0) |
|||
{ |
|||
if (_isSearching) |
|||
{ |
|||
_isSearching = false; |
|||
var restore = _preSearchPage ?? BuildWhatsNewPage(); |
|||
_preSearchPage = null; |
|||
NavigationPage.SetHasBackButton(restore, false); |
|||
_ = _detailNav.ReplaceAsync(restore, new CrossFade(TimeSpan.FromMilliseconds(180))); |
|||
} |
|||
return; |
|||
} |
|||
|
|||
if (!_isSearching) |
|||
{ |
|||
_preSearchPage = _detailNav.CurrentPage as ContentPage; |
|||
_isSearching = true; |
|||
} |
|||
|
|||
var resultsPage = BuildSearchResultsPage(query); |
|||
NavigationPage.SetHasBackButton(resultsPage, false); |
|||
_ = _detailNav.ReplaceAsync(resultsPage, null); |
|||
} |
|||
|
|||
ContentPage BuildSearchResultsPage(string query) |
|||
{ |
|||
var page = new ContentPage { Background = new SolidColorBrush(ContentBg) }; |
|||
page.Header = "Search"; |
|||
|
|||
var scroll = new ScrollViewer(); |
|||
var root = new StackPanel { Spacing = 0 }; |
|||
|
|||
(string Category, string[] Controls)[] allSections = |
|||
{ |
|||
("Basic Input", new[] { "Button", "CheckBox", "ComboBox", "RadioButton", "Slider", "ToggleButton", "ToggleSwitch" }), |
|||
("Collections", new[] { "DataGrid", "ItemsControl", "ListBox", "ListView", "TreeView" }), |
|||
("Date & Time", new[] { "CalendarDatePicker", "DatePicker", "TimePicker" }), |
|||
("Layout", new[] { "Border", "Grid", "Panel", "StackPanel", "WrapPanel" }), |
|||
("Navigation", new[] { "DrawerPage", "NavigationPage", "TabControl", "TabbedPage" }), |
|||
("Text", new[] { "AutoCompleteBox", "RichTextBox", "TextBlock", "TextBox" }), |
|||
}; |
|||
|
|||
var q = query.ToLowerInvariant(); |
|||
bool anyMatch = false; |
|||
|
|||
foreach (var (category, controls) in allSections) |
|||
{ |
|||
var matches = Array.FindAll(controls, c => c.ToLowerInvariant().Contains(q)); |
|||
if (matches.Length == 0) continue; |
|||
|
|||
anyMatch = true; |
|||
root.Children.Add(SectionHeader(category)); |
|||
var chips = new WrapPanel { Margin = new Thickness(24, 4, 24, 0), Orientation = Orientation.Horizontal }; |
|||
foreach (var ctrl in matches) |
|||
chips.Children.Add(new Border |
|||
{ |
|||
Margin = new Thickness(0, 0, 8, 8), |
|||
Padding = new Thickness(12, 6), |
|||
CornerRadius = new CornerRadius(4), |
|||
Background = new SolidColorBrush(CardBg), |
|||
BorderBrush = new SolidColorBrush(BorderCol), |
|||
BorderThickness = new Thickness(1), |
|||
Child = Txt(ctrl, 12, FontWeight.Normal, TextCol), |
|||
}); |
|||
root.Children.Add(chips); |
|||
} |
|||
|
|||
if (!anyMatch) |
|||
{ |
|||
var empty = new StackPanel |
|||
{ |
|||
HorizontalAlignment = HorizontalAlignment.Center, |
|||
Margin = new Thickness(0, 40, 0, 0), |
|||
Spacing = 8, |
|||
}; |
|||
empty.Children.Add(Txt("No results", 16, FontWeight.SemiBold, TextCol)); |
|||
empty.Children.Add(Txt($"No controls match \"{query}\"", 13, FontWeight.Normal, TextSec)); |
|||
root.Children.Add(empty); |
|||
} |
|||
|
|||
scroll.Content = root; |
|||
page.Content = scroll; |
|||
return page; |
|||
} |
|||
|
|||
ContentPage BuildWhatsNewPage() |
|||
{ |
|||
var page = new ContentPage { Background = new SolidColorBrush(ContentBg) }; |
|||
page.Header = "What's New"; |
|||
|
|||
var scroll = new ScrollViewer(); |
|||
var root = new StackPanel { Spacing = 0 }; |
|||
|
|||
var heroBrush = new LinearGradientBrush |
|||
{ |
|||
StartPoint = new RelativePoint(0, 0, RelativeUnit.Relative), |
|||
EndPoint = new RelativePoint(1, 1, RelativeUnit.Relative), |
|||
}; |
|||
heroBrush.GradientStops.Add(new GradientStop(Color.Parse("#003B6F"), 0)); |
|||
heroBrush.GradientStops.Add(new GradientStop(Color.Parse("#0078D4"), 0.5)); |
|||
heroBrush.GradientStops.Add(new GradientStop(Color.Parse("#60CDFF"), 1)); |
|||
|
|||
var heroContent = new StackPanel |
|||
{ |
|||
Margin = new Thickness(24), Spacing = 8, VerticalAlignment = VerticalAlignment.Bottom, |
|||
}; |
|||
heroContent.Children.Add(Txt("NEW IN AVALONIA UI", 11, FontWeight.SemiBold, Accent)); |
|||
heroContent.Children.Add(Txt("Controls Gallery", 28, FontWeight.Bold, TextCol)); |
|||
heroContent.Children.Add(new TextBlock |
|||
{ |
|||
Text = "Explore all controls, styles, and animations available in Avalonia.", |
|||
FontSize = 13, |
|||
Foreground = new SolidColorBrush(Color.FromArgb(200, 255, 255, 255)), |
|||
TextWrapping = TextWrapping.Wrap, |
|||
}); |
|||
|
|||
root.Children.Add(new Border |
|||
{ |
|||
Height = 200, |
|||
Margin = new Thickness(24, 24, 24, 0), |
|||
CornerRadius = new CornerRadius(8), |
|||
Background = heroBrush, |
|||
Child = heroContent, |
|||
}); |
|||
|
|||
root.Children.Add(SectionHeader("New Controls")); |
|||
var wrap = new WrapPanel { Margin = new Thickness(24, 8, 24, 0), Orientation = Orientation.Horizontal, }; |
|||
|
|||
(string Icon, string Title, string Desc)[] newControls = |
|||
{ |
|||
("M12 2L2 7l10 5 10-5-10-5zM2 17l10 5 10-5M2 12l10 5 10-5", |
|||
"DrawerPage", "Master-detail navigation with compact icon rail"), |
|||
("M20 11H7.83l5.59-5.59L12 4l-8 8 8 8 1.41-1.41L7.83 13H20v-2z", |
|||
"NavigationPage", "Push/pop stack with animated transitions"), |
|||
("M3 3h8v8H3zm10 0h8v8h-8zM3 13h8v8H3zm10 0h8v8h-8z", |
|||
"TabbedPage", "Multi-tab layout with swipe navigation"), |
|||
("M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z", |
|||
"ContentPage", "Single-content page with lifecycle events"), |
|||
}; |
|||
foreach (var (icon, title, desc) in newControls) |
|||
wrap.Children.Add(ControlCard(icon, title, desc)); |
|||
root.Children.Add(wrap); |
|||
|
|||
root.Children.Add(SectionHeader("Recently Updated")); |
|||
var updList = new StackPanel { Margin = new Thickness(24, 8, 24, 24), Spacing = 4 }; |
|||
(string Name, string Change)[] updates = |
|||
{ |
|||
("CommandBar", "Overflow menu and compact label mode"), |
|||
("ContentPage", "Lifecycle events and navigation bar customization"), |
|||
}; |
|||
foreach (var (name, change) in updates) |
|||
{ |
|||
var infoStack = new StackPanel { Spacing = 2 }; |
|||
infoStack.Children.Add(Txt(name, 13, FontWeight.SemiBold, TextCol)); |
|||
infoStack.Children.Add(Txt(change, 11, FontWeight.Normal, TextSec)); |
|||
updList.Children.Add(new Border |
|||
{ |
|||
Padding = new Thickness(12, 10), |
|||
CornerRadius = new CornerRadius(4), |
|||
Background = new SolidColorBrush(CardBg), |
|||
BorderBrush = new SolidColorBrush(BorderCol), |
|||
BorderThickness = new Thickness(0, 0, 0, 1), |
|||
Child = infoStack, |
|||
}); |
|||
} |
|||
|
|||
root.Children.Add(updList); |
|||
|
|||
scroll.Content = root; |
|||
page.Content = scroll; |
|||
return page; |
|||
} |
|||
|
|||
Border ControlCard(string iconData, string title, string desc) |
|||
{ |
|||
var stack = new StackPanel { Spacing = 8 }; |
|||
stack.Children.Add(new PathIcon |
|||
{ |
|||
Width = 20, |
|||
Height = 20, |
|||
Data = Geometry.Parse(iconData), |
|||
Foreground = new SolidColorBrush(Accent), |
|||
HorizontalAlignment = HorizontalAlignment.Left, |
|||
}); |
|||
stack.Children.Add(Txt(title, 14, FontWeight.SemiBold, TextCol)); |
|||
stack.Children.Add(new TextBlock |
|||
{ |
|||
Text = desc, FontSize = 11, Foreground = new SolidColorBrush(TextSec), TextWrapping = TextWrapping.Wrap, |
|||
}); |
|||
|
|||
return new Border |
|||
{ |
|||
Width = 182, |
|||
Height = 130, |
|||
Margin = new Thickness(0, 0, 12, 12), |
|||
CornerRadius = new CornerRadius(6), |
|||
Background = new SolidColorBrush(CardBg), |
|||
BorderBrush = new SolidColorBrush(BorderCol), |
|||
BorderThickness = new Thickness(1), |
|||
Padding = new Thickness(16), |
|||
Child = stack, |
|||
}; |
|||
} |
|||
|
|||
ContentPage BuildAllControlsPage() |
|||
{ |
|||
var page = new ContentPage { Background = new SolidColorBrush(ContentBg) }; |
|||
page.Header = "All Controls"; |
|||
|
|||
var scroll = new ScrollViewer(); |
|||
var root = new StackPanel { Spacing = 0 }; |
|||
|
|||
(string Category, string[] Controls)[] sections = |
|||
{ |
|||
("Basic Input", |
|||
new[] |
|||
{ |
|||
"Button", "CheckBox", "ComboBox", "RadioButton", "Slider", "ToggleButton", "ToggleSwitch" |
|||
}), |
|||
("Collections", new[] { "DataGrid", "ItemsControl", "ListBox", "ListView", "TreeView" }), |
|||
("Date & Time", new[] { "CalendarDatePicker", "DatePicker", "TimePicker" }), |
|||
("Layout", new[] { "Border", "Grid", "Panel", "StackPanel", "WrapPanel" }), |
|||
("Navigation", new[] { "DrawerPage", "NavigationPage", "TabControl", "TabbedPage" }), |
|||
("Text", new[] { "AutoCompleteBox", "RichTextBox", "TextBlock", "TextBox" }), |
|||
}; |
|||
|
|||
foreach (var (category, controls) in sections) |
|||
{ |
|||
root.Children.Add(SectionHeader(category)); |
|||
var chips = new WrapPanel { Margin = new Thickness(24, 4, 24, 0), Orientation = Orientation.Horizontal }; |
|||
foreach (var ctrl in controls) |
|||
{ |
|||
chips.Children.Add(new Border |
|||
{ |
|||
Margin = new Thickness(0, 0, 8, 8), |
|||
Padding = new Thickness(12, 6), |
|||
CornerRadius = new CornerRadius(4), |
|||
Background = new SolidColorBrush(CardBg), |
|||
BorderBrush = new SolidColorBrush(BorderCol), |
|||
BorderThickness = new Thickness(1), |
|||
Child = Txt(ctrl, 12, FontWeight.Normal, TextCol), |
|||
}); |
|||
} |
|||
|
|||
root.Children.Add(chips); |
|||
} |
|||
|
|||
scroll.Content = root; |
|||
page.Content = scroll; |
|||
return page; |
|||
} |
|||
|
|||
ContentPage BuildCategoryPage(string title, string description) |
|||
{ |
|||
var page = new ContentPage { Background = new SolidColorBrush(ContentBg) }; |
|||
page.Header = title; |
|||
|
|||
var scroll = new ScrollViewer(); |
|||
var root = new StackPanel { Spacing = 0 }; |
|||
|
|||
var headerStack = new StackPanel { Spacing = 4 }; |
|||
headerStack.Children.Add(Txt(title, 20, FontWeight.SemiBold, TextCol)); |
|||
headerStack.Children.Add(Txt(description, 13, FontWeight.Normal, TextSec)); |
|||
root.Children.Add(new Border |
|||
{ |
|||
Margin = new Thickness(24, 24, 24, 0), |
|||
Padding = new Thickness(16), |
|||
CornerRadius = new CornerRadius(6), |
|||
Background = new SolidColorBrush(CardBg), |
|||
Child = headerStack, |
|||
}); |
|||
|
|||
root.Children.Add(SectionHeader("Controls")); |
|||
var list = new StackPanel { Margin = new Thickness(24, 4, 24, 24), Spacing = 4 }; |
|||
string[] sampleNames = { "Primary Control", "Secondary Control", "Advanced Control", "Variant A", "Variant B" }; |
|||
for (int i = 0; i < sampleNames.Length; i++) |
|||
{ |
|||
var rowGrid = new Grid { ColumnDefinitions = new ColumnDefinitions("*,Auto") }; |
|||
var label = new StackPanel { Spacing = 2 }; |
|||
label.Children.Add(Txt(sampleNames[i], 13, FontWeight.SemiBold, TextCol)); |
|||
label.Children.Add(Txt($"Example usage in {title}", 11, FontWeight.Normal, TextSec)); |
|||
rowGrid.Children.Add(label); |
|||
|
|||
if (i < 2) |
|||
{ |
|||
var badge = new Border |
|||
{ |
|||
Padding = new Thickness(6, 2), |
|||
CornerRadius = new CornerRadius(10), |
|||
Background = new SolidColorBrush(Color.FromArgb(30, 96, 205, 255)), |
|||
Child = Txt("NEW", 10, FontWeight.Bold, Accent), |
|||
HorizontalAlignment = HorizontalAlignment.Right, |
|||
VerticalAlignment = VerticalAlignment.Center, |
|||
}; |
|||
Grid.SetColumn(badge, 1); |
|||
rowGrid.Children.Add(badge); |
|||
} |
|||
|
|||
list.Children.Add(new Border |
|||
{ |
|||
Padding = new Thickness(16, 12), |
|||
CornerRadius = new CornerRadius(4), |
|||
Background = new SolidColorBrush(CardBg), |
|||
BorderBrush = new SolidColorBrush(BorderCol), |
|||
BorderThickness = new Thickness(0, 0, 0, 1), |
|||
Child = rowGrid, |
|||
}); |
|||
} |
|||
|
|||
root.Children.Add(list); |
|||
|
|||
scroll.Content = root; |
|||
page.Content = scroll; |
|||
return page; |
|||
} |
|||
|
|||
ContentPage BuildSettingsPage() |
|||
{ |
|||
var page = new ContentPage { Background = new SolidColorBrush(ContentBg) }; |
|||
page.Header = "Settings"; |
|||
|
|||
var scroll = new ScrollViewer(); |
|||
var root = new StackPanel { Spacing = 0 }; |
|||
|
|||
root.Children.Add(SectionHeader("Appearance")); |
|||
var appearList = new StackPanel { Margin = new Thickness(24, 4, 24, 0), Spacing = 2 }; |
|||
appearList.Children.Add(SettingsRow("App theme", "Dark")); |
|||
appearList.Children.Add(SettingsRow("Accent color", "#60CDFF")); |
|||
appearList.Children.Add(SettingsRow("Font size", "Medium")); |
|||
root.Children.Add(appearList); |
|||
|
|||
root.Children.Add(SectionHeader("About")); |
|||
var aboutList = new StackPanel { Margin = new Thickness(24, 4, 24, 24), Spacing = 2 }; |
|||
aboutList.Children.Add(SettingsRow("Version", "1.0.0")); |
|||
aboutList.Children.Add(SettingsRow("Framework", "Avalonia")); |
|||
aboutList.Children.Add(SettingsRow("Theme", "Fluent")); |
|||
root.Children.Add(aboutList); |
|||
|
|||
scroll.Content = root; |
|||
page.Content = scroll; |
|||
return page; |
|||
} |
|||
|
|||
Border SectionHeader(string title) => new() |
|||
{ |
|||
Margin = new Thickness(24, 20, 24, 0), |
|||
Padding = new Thickness(0, 0, 0, 8), |
|||
BorderBrush = new SolidColorBrush(BorderCol), |
|||
BorderThickness = new Thickness(0, 0, 0, 1), |
|||
Child = Txt(title, 13, FontWeight.SemiBold, Accent), |
|||
}; |
|||
|
|||
static Border SettingsRow(string label, string value) |
|||
{ |
|||
var grid = new Grid { ColumnDefinitions = new ColumnDefinitions("*,Auto") }; |
|||
grid.Children.Add(Txt(label, 13, FontWeight.Normal, TextCol)); |
|||
var val = Txt(value, 12, FontWeight.Normal, TextMuted); |
|||
val.VerticalAlignment = VerticalAlignment.Center; |
|||
Grid.SetColumn(val, 1); |
|||
grid.Children.Add(val); |
|||
|
|||
return new Border |
|||
{ |
|||
Padding = new Thickness(16, 14), |
|||
CornerRadius = new CornerRadius(4), |
|||
Background = new SolidColorBrush(CardBg), |
|||
BorderBrush = new SolidColorBrush(BorderCol), |
|||
BorderThickness = new Thickness(0, 0, 0, 1), |
|||
Child = grid, |
|||
}; |
|||
} |
|||
|
|||
static TextBlock Txt(string text, double size, FontWeight weight, Color color) => new() |
|||
{ |
|||
Text = text, FontSize = size, FontWeight = weight, Foreground = new SolidColorBrush(color), |
|||
}; |
|||
} |
|||
@ -0,0 +1,103 @@ |
|||
<UserControl xmlns="https://github.com/avaloniaui" |
|||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
|||
x:Class="ControlCatalog.Pages.DrawerPageCompactPage"> |
|||
<DockPanel> |
|||
<ScrollViewer DockPanel.Dock="Right" Width="240"> |
|||
<StackPanel Margin="12" Spacing="8"> |
|||
<TextBlock Text="Configuration" FontWeight="SemiBold" FontSize="16" |
|||
Foreground="{DynamicResource SystemControlHighlightAccentBrush}" /> |
|||
|
|||
<TextBlock Text="Layout" FontSize="13" FontWeight="SemiBold" /> |
|||
<ComboBox x:Name="LayoutCombo" SelectedIndex="0" |
|||
SelectionChanged="OnLayoutChanged" HorizontalAlignment="Stretch"> |
|||
<ComboBoxItem Content="CompactOverlay" /> |
|||
<ComboBoxItem Content="CompactInline" /> |
|||
</ComboBox> |
|||
|
|||
<Separator /> |
|||
|
|||
<TextBlock Text="Rail Width" FontSize="12" Opacity="0.7" /> |
|||
<StackPanel Orientation="Horizontal" Spacing="8"> |
|||
<Slider x:Name="CompactLengthSlider" Minimum="40" Maximum="120" Value="56" |
|||
Width="150" ValueChanged="OnCompactLengthChanged" /> |
|||
<TextBlock x:Name="CompactLengthText" Text="56" VerticalAlignment="Center" /> |
|||
</StackPanel> |
|||
|
|||
<TextBlock Text="Open Pane Width" FontSize="12" Opacity="0.7" /> |
|||
<StackPanel Orientation="Horizontal" Spacing="8"> |
|||
<Slider x:Name="DrawerLengthSlider" Minimum="150" Maximum="400" Value="240" |
|||
Width="150" ValueChanged="OnDrawerLengthChanged" /> |
|||
<TextBlock x:Name="DrawerLengthText" Text="240" VerticalAlignment="Center" /> |
|||
</StackPanel> |
|||
|
|||
<Separator /> |
|||
|
|||
<TextBlock Text="Status" FontWeight="SemiBold" FontSize="13" /> |
|||
<TextBlock x:Name="StatusText" Text="Drawer: Closed" Opacity="0.7" TextWrapping="Wrap" /> |
|||
</StackPanel> |
|||
</ScrollViewer> |
|||
|
|||
<Border DockPanel.Dock="Right" Width="1" Background="{DynamicResource SystemControlForegroundBaseMediumLowBrush}" /> |
|||
|
|||
<Border Margin="12" |
|||
BorderBrush="{DynamicResource SystemControlForegroundBaseMediumLowBrush}" |
|||
BorderThickness="1" |
|||
CornerRadius="6" |
|||
ClipToBounds="True"> |
|||
<DrawerPage x:Name="DemoDrawer" |
|||
DrawerLayoutBehavior="CompactOverlay" |
|||
CompactDrawerLength="56" |
|||
DrawerLength="240"> |
|||
<DrawerPage.Drawer> |
|||
<StackPanel Spacing="2" Margin="0,8"> |
|||
<Button HorizontalAlignment="Stretch" Background="Transparent" |
|||
Click="OnMenuItemClick" Tag="Home" ToolTip.Tip="Home"> |
|||
<StackPanel HorizontalAlignment="Center" Spacing="3"> |
|||
<PathIcon Width="20" Height="20" |
|||
Data="M10,20V14H14V20H19V12H22L12,3L2,12H5V20H10Z" |
|||
HorizontalAlignment="Center" /> |
|||
<TextBlock Text="Home" FontSize="9" HorizontalAlignment="Center" /> |
|||
</StackPanel> |
|||
</Button> |
|||
<Button HorizontalAlignment="Stretch" Background="Transparent" |
|||
Click="OnMenuItemClick" Tag="Inbox" ToolTip.Tip="Inbox"> |
|||
<StackPanel HorizontalAlignment="Center" Spacing="3"> |
|||
<PathIcon Width="20" Height="20" |
|||
Data="M20,8L12,13L4,8V6L12,11L20,6M20,4H4C2.89,4 2,4.89 2,6V18A2,2 0 0,0 4,20H20A2,2 0 0,0 22,18V6C22,4.89 21.1,4 20,4Z" |
|||
HorizontalAlignment="Center" /> |
|||
<TextBlock Text="Inbox" FontSize="9" HorizontalAlignment="Center" /> |
|||
</StackPanel> |
|||
</Button> |
|||
<Button HorizontalAlignment="Stretch" Background="Transparent" |
|||
Click="OnMenuItemClick" Tag="Profile" ToolTip.Tip="Profile"> |
|||
<StackPanel HorizontalAlignment="Center" Spacing="3"> |
|||
<PathIcon Width="20" Height="20" |
|||
Data="M12,4A4,4 0 0,1 16,8A4,4 0 0,1 12,12A4,4 0 0,1 8,8A4,4 0 0,1 12,4M12,14C16.42,14 20,15.79 20,18V20H4V18C4,15.79 7.58,14 12,14Z" |
|||
HorizontalAlignment="Center" /> |
|||
<TextBlock Text="Profile" FontSize="9" HorizontalAlignment="Center" /> |
|||
</StackPanel> |
|||
</Button> |
|||
<Button HorizontalAlignment="Stretch" Background="Transparent" |
|||
Click="OnMenuItemClick" Tag="Settings" ToolTip.Tip="Settings"> |
|||
<StackPanel HorizontalAlignment="Center" Spacing="3"> |
|||
<PathIcon Width="20" Height="20" |
|||
Data="M12,15.5A3.5,3.5 0 0,1 8.5,12A3.5,3.5 0 0,1 12,8.5A3.5,3.5 0 0,1 15.5,12A3.5,3.5 0 0,1 12,15.5M19.43,12.97C19.47,12.65 19.5,12.33 19.5,12C19.5,11.67 19.47,11.34 19.43,11L21.54,9.37C21.73,9.22 21.78,8.95 21.66,8.73L19.66,5.27C19.54,5.05 19.27,4.96 19.05,5.05L16.56,6.05C16.04,5.66 15.5,5.32 14.87,5.07L14.5,2.42C14.46,2.18 14.25,2 14,2H10C9.75,2 9.54,2.18 9.5,2.42L9.13,5.07C8.5,5.32 7.96,5.66 7.44,6.05L4.95,5.05C4.73,4.96 4.46,5.05 4.34,5.27L2.34,8.73C2.21,8.95 2.27,9.22 2.46,9.37L4.57,11C4.53,11.34 4.5,11.67 4.5,12C4.5,12.33 4.53,12.65 4.57,12.97L2.46,14.63C2.27,14.78 2.21,15.05 2.34,15.27L4.34,18.73C4.46,18.95 4.73,19.04 4.95,18.95L7.44,17.94C7.96,18.34 8.5,18.68 9.13,18.93L9.5,21.58C9.54,21.82 9.75,22 10,22H14C14.25,22 14.46,21.82 14.5,21.58L14.87,18.93C15.5,18.68 16.04,18.34 16.56,17.94L19.05,18.95C19.27,19.04 19.54,18.95 19.66,18.73L21.66,15.27C21.78,15.05 21.73,14.78 21.54,14.63L19.43,12.97Z" |
|||
HorizontalAlignment="Center" /> |
|||
<TextBlock Text="Settings" FontSize="9" HorizontalAlignment="Center" /> |
|||
</StackPanel> |
|||
</Button> |
|||
</StackPanel> |
|||
</DrawerPage.Drawer> |
|||
<DrawerPage.Content> |
|||
<ContentPage x:Name="DetailPage" Header="Home"> |
|||
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center" Spacing="8"> |
|||
<TextBlock x:Name="DetailTitleText" Text="Home" FontSize="24" FontWeight="Bold" HorizontalAlignment="Center" /> |
|||
<TextBlock Text="Select an item from the compact rail on the left." |
|||
FontSize="13" Opacity="0.7" TextWrapping="Wrap" TextAlignment="Center" MaxWidth="280" /> |
|||
</StackPanel> |
|||
</ContentPage> |
|||
</DrawerPage.Content> |
|||
</DrawerPage> |
|||
</Border> |
|||
</DockPanel> |
|||
</UserControl> |
|||
@ -0,0 +1,78 @@ |
|||
using Avalonia.Controls; |
|||
using Avalonia.Controls.Primitives; |
|||
using Avalonia.Interactivity; |
|||
|
|||
namespace ControlCatalog.Pages |
|||
{ |
|||
public partial class DrawerPageCompactPage : UserControl |
|||
{ |
|||
private bool _isLoaded; |
|||
|
|||
public DrawerPageCompactPage() |
|||
{ |
|||
InitializeComponent(); |
|||
} |
|||
|
|||
protected override void OnLoaded(RoutedEventArgs e) |
|||
{ |
|||
base.OnLoaded(e); |
|||
_isLoaded = true; |
|||
DemoDrawer.Opened += OnDrawerStatusChanged; |
|||
DemoDrawer.Closed += OnDrawerStatusChanged; |
|||
} |
|||
|
|||
protected override void OnUnloaded(RoutedEventArgs e) |
|||
{ |
|||
base.OnUnloaded(e); |
|||
DemoDrawer.Opened -= OnDrawerStatusChanged; |
|||
DemoDrawer.Closed -= OnDrawerStatusChanged; |
|||
} |
|||
|
|||
private void OnDrawerStatusChanged(object? sender, System.EventArgs e) => UpdateStatus(); |
|||
|
|||
private void OnLayoutChanged(object? sender, SelectionChangedEventArgs e) |
|||
{ |
|||
if (!_isLoaded) |
|||
return; |
|||
DemoDrawer.DrawerLayoutBehavior = LayoutCombo.SelectedIndex switch |
|||
{ |
|||
0 => DrawerLayoutBehavior.CompactOverlay, |
|||
1 => DrawerLayoutBehavior.CompactInline, |
|||
_ => DrawerLayoutBehavior.CompactOverlay |
|||
}; |
|||
} |
|||
|
|||
private void OnCompactLengthChanged(object? sender, RangeBaseValueChangedEventArgs e) |
|||
{ |
|||
if (!_isLoaded) |
|||
return; |
|||
DemoDrawer.CompactDrawerLength = e.NewValue; |
|||
CompactLengthText.Text = ((int)e.NewValue).ToString(); |
|||
} |
|||
|
|||
private void OnDrawerLengthChanged(object? sender, RangeBaseValueChangedEventArgs e) |
|||
{ |
|||
if (!_isLoaded) |
|||
return; |
|||
DemoDrawer.DrawerLength = e.NewValue; |
|||
DrawerLengthText.Text = ((int)e.NewValue).ToString(); |
|||
} |
|||
|
|||
private void OnMenuItemClick(object? sender, RoutedEventArgs e) |
|||
{ |
|||
if (!_isLoaded) |
|||
return; |
|||
if (sender is not Button button) |
|||
return; |
|||
var item = button.Tag?.ToString() ?? "Home"; |
|||
DetailTitleText.Text = item; |
|||
DetailPage.Header = item; |
|||
DemoDrawer.IsOpen = false; |
|||
} |
|||
|
|||
private void UpdateStatus() |
|||
{ |
|||
StatusText.Text = $"Drawer: {(DemoDrawer.IsOpen ? "Open" : "Closed")}"; |
|||
} |
|||
} |
|||
} |
|||