Browse Source

Merge branch 'master' into fix/Platform/Windows/WindowsInputPane/Leak

pull/16916/head
workgroupengineering 2 weeks ago
committed by GitHub
parent
commit
0d33c4b6a6
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 1
      Avalonia.Desktop.slnf
  2. 1
      Avalonia.sln
  3. 14
      Directory.Packages.props
  4. 40
      api/Avalonia.LinuxFramebuffer.nupkg.xml
  5. 64
      api/Avalonia.Skia.nupkg.xml
  6. 1124
      api/Avalonia.nupkg.xml
  7. 3
      native/Avalonia.Native/src/OSX/WindowImpl.h
  8. 44
      native/Avalonia.Native/src/OSX/WindowImpl.mm
  9. BIN
      samples/ControlCatalog/Assets/CurvedHeader/avatar.jpg
  10. BIN
      samples/ControlCatalog/Assets/CurvedHeader/featured.jpg
  11. BIN
      samples/ControlCatalog/Assets/CurvedHeader/product1.jpg
  12. BIN
      samples/ControlCatalog/Assets/CurvedHeader/product2.jpg
  13. BIN
      samples/ControlCatalog/Assets/CurvedHeader/product3.jpg
  14. BIN
      samples/ControlCatalog/Assets/CurvedHeader/update1.jpg
  15. BIN
      samples/ControlCatalog/Assets/CurvedHeader/update2.jpg
  16. BIN
      samples/ControlCatalog/Assets/CurvedHeader/update3.jpg
  17. BIN
      samples/ControlCatalog/Assets/ModernApp/avatar.jpg
  18. BIN
      samples/ControlCatalog/Assets/ModernApp/dest_alps.jpg
  19. BIN
      samples/ControlCatalog/Assets/ModernApp/dest_forest.jpg
  20. BIN
      samples/ControlCatalog/Assets/ModernApp/dest_norway.jpg
  21. BIN
      samples/ControlCatalog/Assets/ModernApp/exp_angkor.jpg
  22. BIN
      samples/ControlCatalog/Assets/ModernApp/exp_tokyo.jpg
  23. BIN
      samples/ControlCatalog/Assets/ModernApp/gallery_alpine.jpg
  24. BIN
      samples/ControlCatalog/Assets/ModernApp/gallery_bay.jpg
  25. BIN
      samples/ControlCatalog/Assets/ModernApp/gallery_city.jpg
  26. BIN
      samples/ControlCatalog/Assets/ModernApp/gallery_paris.jpg
  27. BIN
      samples/ControlCatalog/Assets/ModernApp/gallery_tropical.jpg
  28. BIN
      samples/ControlCatalog/Assets/ModernApp/gallery_venice.jpg
  29. BIN
      samples/ControlCatalog/Assets/ModernApp/story1.jpg
  30. BIN
      samples/ControlCatalog/Assets/ModernApp/story2.jpg
  31. BIN
      samples/ControlCatalog/Assets/ModernApp/story3.jpg
  32. BIN
      samples/ControlCatalog/Assets/Movies/cast1.jpg
  33. BIN
      samples/ControlCatalog/Assets/Movies/cast2.jpg
  34. BIN
      samples/ControlCatalog/Assets/Movies/continue1.jpg
  35. BIN
      samples/ControlCatalog/Assets/Movies/hero.jpg
  36. BIN
      samples/ControlCatalog/Assets/Movies/morelike1.jpg
  37. BIN
      samples/ControlCatalog/Assets/Movies/search1.jpg
  38. BIN
      samples/ControlCatalog/Assets/Movies/toprated1.jpg
  39. BIN
      samples/ControlCatalog/Assets/Movies/toprated2.jpg
  40. BIN
      samples/ControlCatalog/Assets/Movies/toprated3.jpg
  41. BIN
      samples/ControlCatalog/Assets/Movies/toprated4.jpg
  42. BIN
      samples/ControlCatalog/Assets/Movies/trending1.jpg
  43. BIN
      samples/ControlCatalog/Assets/Movies/trending2.jpg
  44. BIN
      samples/ControlCatalog/Assets/Pulse/cat_hiit.jpg
  45. BIN
      samples/ControlCatalog/Assets/Pulse/cat_strength.jpg
  46. BIN
      samples/ControlCatalog/Assets/Pulse/cat_yoga.jpg
  47. BIN
      samples/ControlCatalog/Assets/Pulse/ex_bench.jpg
  48. BIN
      samples/ControlCatalog/Assets/Pulse/ex_deadlifts.jpg
  49. BIN
      samples/ControlCatalog/Assets/Pulse/ex_overhead.jpg
  50. BIN
      samples/ControlCatalog/Assets/Pulse/ex_pullups.jpg
  51. BIN
      samples/ControlCatalog/Assets/Pulse/ex_squats.jpg
  52. BIN
      samples/ControlCatalog/Assets/Pulse/profile_avatar.jpg
  53. BIN
      samples/ControlCatalog/Assets/Pulse/rec_fullbody.jpg
  54. BIN
      samples/ControlCatalog/Assets/Pulse/rec_mobility.jpg
  55. BIN
      samples/ControlCatalog/Assets/Pulse/rec_powercore.jpg
  56. BIN
      samples/ControlCatalog/Assets/Pulse/workout_hero.jpg
  57. BIN
      samples/ControlCatalog/Assets/Restaurant/dish1.jpg
  58. BIN
      samples/ControlCatalog/Assets/Restaurant/dish2.jpg
  59. BIN
      samples/ControlCatalog/Assets/Restaurant/dish3.jpg
  60. BIN
      samples/ControlCatalog/Assets/Restaurant/dish4.jpg
  61. BIN
      samples/ControlCatalog/Assets/Restaurant/featured_dish.jpg
  62. BIN
      samples/ControlCatalog/Assets/Restaurant/user_avatar.jpg
  63. BIN
      samples/ControlCatalog/Assets/RetroGaming/cyber_city.jpg
  64. BIN
      samples/ControlCatalog/Assets/RetroGaming/dungeon_bit.jpg
  65. BIN
      samples/ControlCatalog/Assets/RetroGaming/forest_spirit.jpg
  66. BIN
      samples/ControlCatalog/Assets/RetroGaming/hero.jpg
  67. BIN
      samples/ControlCatalog/Assets/RetroGaming/neon_ninja.jpg
  68. BIN
      samples/ControlCatalog/Assets/RetroGaming/neon_racer.jpg
  69. BIN
      samples/ControlCatalog/Assets/RetroGaming/pixel_quest.jpg
  70. BIN
      samples/ControlCatalog/Assets/RetroGaming/space_voids.jpg
  71. 6
      samples/ControlCatalog/ControlCatalog.csproj
  72. 10
      samples/ControlCatalog/DecoratedWindow.xaml
  73. 32
      samples/ControlCatalog/MainView.xaml
  74. 6
      samples/ControlCatalog/MainView.xaml.cs
  75. 1
      samples/ControlCatalog/MainWindow.xaml
  76. 120
      samples/ControlCatalog/Pages/CommandBar/CommandBarCustomizationPage.xaml
  77. 90
      samples/ControlCatalog/Pages/CommandBar/CommandBarCustomizationPage.xaml.cs
  78. 75
      samples/ControlCatalog/Pages/CommandBar/CommandBarDynamicOverflowPage.xaml
  79. 45
      samples/ControlCatalog/Pages/CommandBar/CommandBarDynamicOverflowPage.xaml.cs
  80. 94
      samples/ControlCatalog/Pages/CommandBar/CommandBarFirstLookPage.xaml
  81. 27
      samples/ControlCatalog/Pages/CommandBar/CommandBarFirstLookPage.xaml.cs
  82. 47
      samples/ControlCatalog/Pages/CommandBar/CommandBarLabelPositionPage.xaml
  83. 12
      samples/ControlCatalog/Pages/CommandBar/CommandBarLabelPositionPage.xaml.cs
  84. 74
      samples/ControlCatalog/Pages/CommandBar/CommandBarOverflowPage.xaml
  85. 54
      samples/ControlCatalog/Pages/CommandBar/CommandBarOverflowPage.xaml.cs
  86. 77
      samples/ControlCatalog/Pages/CommandBar/CommandBarTogglePage.xaml
  87. 50
      samples/ControlCatalog/Pages/CommandBar/CommandBarTogglePage.xaml.cs
  88. 8
      samples/ControlCatalog/Pages/CommandBarPage.xaml
  89. 158
      samples/ControlCatalog/Pages/CommandBarPage.xaml.cs
  90. 11
      samples/ControlCatalog/Pages/ConnectedAnimationDemoPage.xaml
  91. 144
      samples/ControlCatalog/Pages/ConnectedAnimationDemoPage.xaml.cs
  92. 11
      samples/ControlCatalog/Pages/ContentDemoPage.xaml
  93. 160
      samples/ControlCatalog/Pages/ContentDemoPage.xaml.cs
  94. 63
      samples/ControlCatalog/Pages/ContentPage/ContentPageCommandBarPage.xaml
  95. 212
      samples/ControlCatalog/Pages/ContentPage/ContentPageCommandBarPage.xaml.cs
  96. 106
      samples/ControlCatalog/Pages/ContentPage/ContentPageCustomizationPage.xaml
  97. 64
      samples/ControlCatalog/Pages/ContentPage/ContentPageCustomizationPage.xaml.cs
  98. 66
      samples/ControlCatalog/Pages/ContentPage/ContentPageEventsPage.xaml
  99. 103
      samples/ControlCatalog/Pages/ContentPage/ContentPageEventsPage.xaml.cs
  100. 48
      samples/ControlCatalog/Pages/ContentPage/ContentPageFirstLookPage.xaml

1
Avalonia.Desktop.slnf

@ -64,6 +64,7 @@
"tests\\Avalonia.Headless.XUnit.PerAssembly.UnitTests\\Avalonia.Headless.XUnit.PerAssembly.UnitTests.csproj",
"tests\\Avalonia.Headless.XUnit.PerTest.UnitTests\\Avalonia.Headless.XUnit.PerTest.UnitTests.csproj",
"tests\\Avalonia.IntegrationTests.Appium\\Avalonia.IntegrationTests.Appium.csproj",
"tests\\Avalonia.IntegrationTests.Win32\\Avalonia.IntegrationTests.Win32.csproj",
"tests\\Avalonia.LeakTests\\Avalonia.LeakTests.csproj",
"tests\\Avalonia.Markup.UnitTests\\Avalonia.Markup.UnitTests.csproj",
"tests\\Avalonia.Markup.Xaml.UnitTests\\Avalonia.Markup.Xaml.UnitTests.csproj",

1
Avalonia.sln

@ -207,6 +207,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
NOTICE.md = NOTICE.md
NuGet.Config = NuGet.Config
readme.md = readme.md
Directory.Packages.props = Directory.Packages.props
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Generators", "src\tools\Avalonia.Generators\Avalonia.Generators.csproj", "{DDA28789-C21A-4654-86CE-D01E81F095C5}"

14
Directory.Packages.props

@ -12,9 +12,9 @@
<PackageVersion Include="CommunityToolkit.Mvvm" Version="8.4.0" />
<PackageVersion Include="Dotnet.Bundle" Version="0.9.13" />
<PackageVersion Include="GtkSharp" Version="3.24.24.95" />
<PackageVersion Include="HarfBuzzSharp" Version="8.3.1.2" />
<PackageVersion Include="HarfBuzzSharp.NativeAssets.Linux" Version="8.3.1.2" />
<PackageVersion Include="HarfBuzzSharp.NativeAssets.WebAssembly" Version="8.3.1.2" />
<PackageVersion Include="HarfBuzzSharp" Version="8.3.1.3" />
<PackageVersion Include="HarfBuzzSharp.NativeAssets.Linux" Version="8.3.1.3" />
<PackageVersion Include="HarfBuzzSharp.NativeAssets.WebAssembly" Version="8.3.1.3" />
<PackageVersion Include="MicroCom.CodeGenerator" Version="0.11.0" />
<PackageVersion Include="MicroCom.CodeGenerator.MSBuild" Version="0.11.0" />
<PackageVersion Include="MicroCom.Runtime" Version="0.11.0" />
@ -46,9 +46,9 @@
<PackageVersion Include="Silk.NET.Vulkan.Extensions.EXT" Version="2.22.0" />
<PackageVersion Include="Silk.NET.Vulkan.Extensions.KHR" Version="2.22.0" />
<PackageVersion Include="SixLabors.ImageSharp" Version="2.1.12" />
<PackageVersion Include="SkiaSharp" Version="3.119.1" />
<PackageVersion Include="SkiaSharp.NativeAssets.Linux" Version="3.119.1" />
<PackageVersion Include="SkiaSharp.NativeAssets.WebAssembly" Version="3.119.1" />
<PackageVersion Include="SkiaSharp" Version="3.119.3-preview.1.1" />
<PackageVersion Include="SkiaSharp.NativeAssets.Linux" Version="3.119.3-preview.1.1" />
<PackageVersion Include="SkiaSharp.NativeAssets.WebAssembly" Version="3.119.3-preview.1.1" />
<PackageVersion Include="System.ComponentModel.Annotations" Version="4.5.0" />
<PackageVersion Include="System.Diagnostics.DiagnosticSource" Version="9.0.10" />
<PackageVersion Include="System.Memory" Version="4.5.5" />
@ -59,7 +59,7 @@
<PackageVersion Include="System.Runtime.CompilerServices.Unsafe" Version="6.1.2" />
<PackageVersion Include="System.Text.Json" Version="10.0.0" />
<PackageVersion Include="System.Text.RegularExpressions" Version="4.3.1" />
<PackageVersion Include="Tmds.DBus.Protocol" Version="0.21.2" />
<PackageVersion Include="Tmds.DBus.Protocol" Version="0.90.3" />
<PackageVersion Include="Tmds.DBus.SourceGenerator" Version="0.0.22" />
<PackageVersion Include="Xamarin.AndroidX.AppCompat" Version="1.7.1.1" />
<PackageVersion Include="Xamarin.AndroidX.Core.SplashScreen" Version="1.2.0" />

40
api/Avalonia.LinuxFramebuffer.nupkg.xml

@ -0,0 +1,40 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- https://learn.microsoft.com/dotnet/fundamentals/package-validation/diagnostic-ids -->
<Suppressions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Suppression>
<DiagnosticId>CP0002</DiagnosticId>
<Target>M:Avalonia.LinuxFramebuffer.FbdevOutput.CreateFramebufferRenderTarget</Target>
<Left>baseline/Avalonia.LinuxFramebuffer/lib/net10.0/Avalonia.LinuxFramebuffer.dll</Left>
<Right>current/Avalonia.LinuxFramebuffer/lib/net10.0/Avalonia.LinuxFramebuffer.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0002</DiagnosticId>
<Target>M:Avalonia.LinuxFramebuffer.FbdevOutput.Lock</Target>
<Left>baseline/Avalonia.LinuxFramebuffer/lib/net10.0/Avalonia.LinuxFramebuffer.dll</Left>
<Right>current/Avalonia.LinuxFramebuffer/lib/net10.0/Avalonia.LinuxFramebuffer.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0002</DiagnosticId>
<Target>M:Avalonia.LinuxFramebuffer.FbdevOutput.CreateFramebufferRenderTarget</Target>
<Left>baseline/Avalonia.LinuxFramebuffer/lib/net8.0/Avalonia.LinuxFramebuffer.dll</Left>
<Right>current/Avalonia.LinuxFramebuffer/lib/net8.0/Avalonia.LinuxFramebuffer.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0002</DiagnosticId>
<Target>M:Avalonia.LinuxFramebuffer.FbdevOutput.Lock</Target>
<Left>baseline/Avalonia.LinuxFramebuffer/lib/net8.0/Avalonia.LinuxFramebuffer.dll</Left>
<Right>current/Avalonia.LinuxFramebuffer/lib/net8.0/Avalonia.LinuxFramebuffer.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0008</DiagnosticId>
<Target>T:Avalonia.LinuxFramebuffer.FbdevOutput</Target>
<Left>baseline/Avalonia.LinuxFramebuffer/lib/net10.0/Avalonia.LinuxFramebuffer.dll</Left>
<Right>current/Avalonia.LinuxFramebuffer/lib/net10.0/Avalonia.LinuxFramebuffer.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0008</DiagnosticId>
<Target>T:Avalonia.LinuxFramebuffer.FbdevOutput</Target>
<Left>baseline/Avalonia.LinuxFramebuffer/lib/net8.0/Avalonia.LinuxFramebuffer.dll</Left>
<Right>current/Avalonia.LinuxFramebuffer/lib/net8.0/Avalonia.LinuxFramebuffer.dll</Right>
</Suppression>
</Suppressions>

64
api/Avalonia.Skia.nupkg.xml

@ -1,6 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<!-- https://learn.microsoft.com/dotnet/fundamentals/package-validation/diagnostic-ids -->
<Suppressions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:Avalonia.Skia.ISkiaGpu</Target>
<Left>baseline/Avalonia.Skia/lib/net10.0/Avalonia.Skia.dll</Left>
<Right>current/Avalonia.Skia/lib/net10.0/Avalonia.Skia.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:Avalonia.Skia.ISkiaGpuRenderTarget2</Target>
@ -13,6 +19,12 @@
<Left>baseline/Avalonia.Skia/lib/net10.0/Avalonia.Skia.dll</Left>
<Right>current/Avalonia.Skia/lib/net10.0/Avalonia.Skia.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:Avalonia.Skia.ISkiaGpu</Target>
<Left>baseline/Avalonia.Skia/lib/net8.0/Avalonia.Skia.dll</Left>
<Right>current/Avalonia.Skia/lib/net8.0/Avalonia.Skia.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:Avalonia.Skia.ISkiaGpuRenderTarget2</Target>
@ -31,30 +43,66 @@
<Left>baseline/Avalonia.Skia/lib/net10.0/Avalonia.Skia.dll</Left>
<Right>current/Avalonia.Skia/lib/net10.0/Avalonia.Skia.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0002</DiagnosticId>
<Target>M:Avalonia.Skia.ISkiaGpu.TryCreateRenderTarget(System.Collections.Generic.IEnumerable{System.Object})</Target>
<Left>baseline/Avalonia.Skia/lib/net10.0/Avalonia.Skia.dll</Left>
<Right>current/Avalonia.Skia/lib/net10.0/Avalonia.Skia.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0002</DiagnosticId>
<Target>M:Avalonia.Skia.ISkiaGpuRenderTarget.BeginRenderingSession</Target>
<Left>baseline/Avalonia.Skia/lib/net10.0/Avalonia.Skia.dll</Left>
<Right>current/Avalonia.Skia/lib/net10.0/Avalonia.Skia.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0002</DiagnosticId>
<Target>M:Avalonia.Skia.ISkiaGpuRenderTarget.BeginRenderingSession(System.Nullable{Avalonia.PixelSize})</Target>
<Left>baseline/Avalonia.Skia/lib/net10.0/Avalonia.Skia.dll</Left>
<Right>current/Avalonia.Skia/lib/net10.0/Avalonia.Skia.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0002</DiagnosticId>
<Target>M:Avalonia.Skia.Helpers.DrawingContextHelper.WrapSkiaCanvas(SkiaSharp.SKCanvas,Avalonia.Vector)</Target>
<Left>baseline/Avalonia.Skia/lib/net8.0/Avalonia.Skia.dll</Left>
<Right>current/Avalonia.Skia/lib/net8.0/Avalonia.Skia.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0002</DiagnosticId>
<Target>M:Avalonia.Skia.ISkiaGpu.TryCreateRenderTarget(System.Collections.Generic.IEnumerable{System.Object})</Target>
<Left>baseline/Avalonia.Skia/lib/net8.0/Avalonia.Skia.dll</Left>
<Right>current/Avalonia.Skia/lib/net8.0/Avalonia.Skia.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0002</DiagnosticId>
<Target>M:Avalonia.Skia.ISkiaGpuRenderTarget.BeginRenderingSession</Target>
<Left>baseline/Avalonia.Skia/lib/net8.0/Avalonia.Skia.dll</Left>
<Right>current/Avalonia.Skia/lib/net8.0/Avalonia.Skia.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0002</DiagnosticId>
<Target>M:Avalonia.Skia.ISkiaGpuRenderTarget.BeginRenderingSession(System.Nullable{Avalonia.PixelSize})</Target>
<Left>baseline/Avalonia.Skia/lib/net8.0/Avalonia.Skia.dll</Left>
<Right>current/Avalonia.Skia/lib/net8.0/Avalonia.Skia.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0006</DiagnosticId>
<Target>M:Avalonia.Skia.ISkiaGpu.TryCreateRenderTarget(System.Collections.Generic.IEnumerable{Avalonia.Platform.Surfaces.IPlatformRenderSurface})</Target>
<Left>baseline/Avalonia.Skia/lib/net10.0/Avalonia.Skia.dll</Left>
<Right>current/Avalonia.Skia/lib/net10.0/Avalonia.Skia.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0006</DiagnosticId>
<Target>M:Avalonia.Skia.ISkiaGpu.TryGetGrContext</Target>
<Left>baseline/Avalonia.Skia/lib/net10.0/Avalonia.Skia.dll</Left>
<Right>current/Avalonia.Skia/lib/net10.0/Avalonia.Skia.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0006</DiagnosticId>
<Target>M:Avalonia.Skia.ISkiaGpuRenderTarget.BeginRenderingSession(Avalonia.Platform.IRenderTarget.RenderTargetSceneInfo)</Target>
<Left>baseline/Avalonia.Skia/lib/net10.0/Avalonia.Skia.dll</Left>
<Right>current/Avalonia.Skia/lib/net10.0/Avalonia.Skia.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0006</DiagnosticId>
<Target>M:Avalonia.Skia.ISkiaGpuRenderTarget.BeginRenderingSession(System.Nullable{Avalonia.PixelSize})</Target>
@ -67,12 +115,24 @@
<Left>baseline/Avalonia.Skia/lib/net10.0/Avalonia.Skia.dll</Left>
<Right>current/Avalonia.Skia/lib/net10.0/Avalonia.Skia.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0006</DiagnosticId>
<Target>M:Avalonia.Skia.ISkiaGpu.TryCreateRenderTarget(System.Collections.Generic.IEnumerable{Avalonia.Platform.Surfaces.IPlatformRenderSurface})</Target>
<Left>baseline/Avalonia.Skia/lib/net8.0/Avalonia.Skia.dll</Left>
<Right>current/Avalonia.Skia/lib/net8.0/Avalonia.Skia.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0006</DiagnosticId>
<Target>M:Avalonia.Skia.ISkiaGpu.TryGetGrContext</Target>
<Left>baseline/Avalonia.Skia/lib/net8.0/Avalonia.Skia.dll</Left>
<Right>current/Avalonia.Skia/lib/net8.0/Avalonia.Skia.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0006</DiagnosticId>
<Target>M:Avalonia.Skia.ISkiaGpuRenderTarget.BeginRenderingSession(Avalonia.Platform.IRenderTarget.RenderTargetSceneInfo)</Target>
<Left>baseline/Avalonia.Skia/lib/net8.0/Avalonia.Skia.dll</Left>
<Right>current/Avalonia.Skia/lib/net8.0/Avalonia.Skia.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0006</DiagnosticId>
<Target>M:Avalonia.Skia.ISkiaGpuRenderTarget.BeginRenderingSession(System.Nullable{Avalonia.PixelSize})</Target>
@ -109,4 +169,4 @@
<Left>baseline/Avalonia.Skia/lib/net8.0/Avalonia.Skia.dll</Left>
<Right>current/Avalonia.Skia/lib/net8.0/Avalonia.Skia.dll</Right>
</Suppression>
</Suppressions>
</Suppressions>

1124
api/Avalonia.nupkg.xml

File diff suppressed because it is too large

3
native/Avalonia.Native/src/OSX/WindowImpl.h

@ -62,8 +62,6 @@ BEGIN_INTERFACE_MAP()
virtual HRESULT SetExtendClientArea (bool enable) override;
virtual HRESULT SetExtendClientAreaHints (AvnExtendClientAreaChromeHints hints) override;
virtual HRESULT GetExtendTitleBarHeight (double*ret) override;
virtual HRESULT SetExtendTitleBarHeight (double value) override;
@ -110,7 +108,6 @@ private:
NSRect _preZoomSize;
bool _transitioningWindowState;
bool _isClientAreaExtended;
AvnExtendClientAreaChromeHints _extendClientHints;
bool _isModal;
};

44
native/Avalonia.Native/src/OSX/WindowImpl.mm

@ -13,7 +13,6 @@
WindowImpl::WindowImpl(IAvnWindowEvents *events) : TopLevelImpl(events), WindowBaseImpl(events, false) {
_isEnabled = true;
_isClientAreaExtended = false;
_extendClientHints = AvnDefaultChrome;
_fullScreenActive = false;
_canResize = true;
_canMinimize = true;
@ -153,20 +152,11 @@ void WindowImpl::WindowStateChanged() {
if (_isClientAreaExtended) {
if (_lastWindowState == FullScreen) {
// we exited fs.
if (_extendClientHints & AvnOSXThickTitleBar) {
Window.toolbar = [NSToolbar new];
Window.toolbar.showsBaselineSeparator = false;
}
[Window setTitlebarAppearsTransparent:true];
[StandardContainer setFrameSize:StandardContainer.frame.size];
} else if (state == FullScreen) {
// we entered fs.
if (_extendClientHints & AvnOSXThickTitleBar) {
Window.toolbar = nullptr;
}
[Window setTitlebarAppearsTransparent:false];
[StandardContainer setFrameSize:StandardContainer.frame.size];
@ -240,6 +230,10 @@ HRESULT WindowImpl::SetDecorations(SystemDecorations value) {
UpdateAppearance();
if (_isClientAreaExtended) {
[StandardContainer ShowTitleBar:_decorations == SystemDecorationsFull];
}
switch (_decorations) {
case SystemDecorationsNone:
[Window setHasShadow:NO];
@ -391,20 +385,9 @@ HRESULT WindowImpl::SetExtendClientArea(bool enable) {
[Window setTitlebarAppearsTransparent:true];
auto wantsTitleBar = (_extendClientHints & AvnSystemChrome) || (_extendClientHints & AvnPreferSystemChrome);
if (wantsTitleBar) {
[StandardContainer ShowTitleBar:true];
} else {
[StandardContainer ShowTitleBar:false];
}
[StandardContainer ShowTitleBar:_decorations == SystemDecorationsFull];
if (_extendClientHints & AvnOSXThickTitleBar) {
Window.toolbar = [NSToolbar new];
Window.toolbar.showsBaselineSeparator = false;
} else {
Window.toolbar = nullptr;
}
Window.toolbar = nullptr;
} else {
Window.titleVisibility = NSWindowTitleVisible;
Window.toolbar = nullptr;
@ -420,17 +403,6 @@ HRESULT WindowImpl::SetExtendClientArea(bool enable) {
}
}
HRESULT WindowImpl::SetExtendClientAreaHints(AvnExtendClientAreaChromeHints hints) {
START_COM_CALL;
@autoreleasepool {
_extendClientHints = hints;
SetExtendClientArea(_isClientAreaExtended);
return S_OK;
}
}
HRESULT WindowImpl::GetExtendTitleBarHeight(double *ret) {
START_COM_CALL;
@ -619,9 +591,7 @@ void WindowImpl::UpdateAppearance() {
return;
}
bool wantsChrome = (_extendClientHints & AvnSystemChrome) || (_extendClientHints & AvnPreferSystemChrome);
bool hasTrafficLights = (_decorations == SystemDecorationsFull) &&
(_isClientAreaExtended ? wantsChrome : true);
bool hasTrafficLights = (_decorations == SystemDecorationsFull);
NSButton* closeButton = [Window standardWindowButton:NSWindowCloseButton];
NSButton* miniaturizeButton = [Window standardWindowButton:NSWindowMiniaturizeButton];

BIN
samples/ControlCatalog/Assets/CurvedHeader/avatar.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 264 KiB

BIN
samples/ControlCatalog/Assets/CurvedHeader/featured.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 334 KiB

BIN
samples/ControlCatalog/Assets/CurvedHeader/product1.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 383 KiB

BIN
samples/ControlCatalog/Assets/CurvedHeader/product2.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 305 KiB

BIN
samples/ControlCatalog/Assets/CurvedHeader/product3.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 307 KiB

BIN
samples/ControlCatalog/Assets/CurvedHeader/update1.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 197 KiB

BIN
samples/ControlCatalog/Assets/CurvedHeader/update2.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 198 KiB

BIN
samples/ControlCatalog/Assets/CurvedHeader/update3.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 214 KiB

BIN
samples/ControlCatalog/Assets/ModernApp/avatar.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

BIN
samples/ControlCatalog/Assets/ModernApp/dest_alps.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

BIN
samples/ControlCatalog/Assets/ModernApp/dest_forest.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

BIN
samples/ControlCatalog/Assets/ModernApp/dest_norway.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

BIN
samples/ControlCatalog/Assets/ModernApp/exp_angkor.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

BIN
samples/ControlCatalog/Assets/ModernApp/exp_tokyo.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 102 KiB

BIN
samples/ControlCatalog/Assets/ModernApp/gallery_alpine.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

BIN
samples/ControlCatalog/Assets/ModernApp/gallery_bay.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

BIN
samples/ControlCatalog/Assets/ModernApp/gallery_city.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

BIN
samples/ControlCatalog/Assets/ModernApp/gallery_paris.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

BIN
samples/ControlCatalog/Assets/ModernApp/gallery_tropical.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

BIN
samples/ControlCatalog/Assets/ModernApp/gallery_venice.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

BIN
samples/ControlCatalog/Assets/ModernApp/story1.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

BIN
samples/ControlCatalog/Assets/ModernApp/story2.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

BIN
samples/ControlCatalog/Assets/ModernApp/story3.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

BIN
samples/ControlCatalog/Assets/Movies/cast1.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 375 KiB

BIN
samples/ControlCatalog/Assets/Movies/cast2.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 375 KiB

BIN
samples/ControlCatalog/Assets/Movies/continue1.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 238 KiB

BIN
samples/ControlCatalog/Assets/Movies/hero.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 357 KiB

BIN
samples/ControlCatalog/Assets/Movies/morelike1.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 378 KiB

BIN
samples/ControlCatalog/Assets/Movies/search1.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 357 KiB

BIN
samples/ControlCatalog/Assets/Movies/toprated1.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 315 KiB

BIN
samples/ControlCatalog/Assets/Movies/toprated2.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 189 KiB

BIN
samples/ControlCatalog/Assets/Movies/toprated3.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 270 KiB

BIN
samples/ControlCatalog/Assets/Movies/toprated4.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 330 KiB

BIN
samples/ControlCatalog/Assets/Movies/trending1.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 347 KiB

BIN
samples/ControlCatalog/Assets/Movies/trending2.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 352 KiB

BIN
samples/ControlCatalog/Assets/Pulse/cat_hiit.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 354 KiB

BIN
samples/ControlCatalog/Assets/Pulse/cat_strength.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 321 KiB

BIN
samples/ControlCatalog/Assets/Pulse/cat_yoga.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 215 KiB

BIN
samples/ControlCatalog/Assets/Pulse/ex_bench.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 340 KiB

BIN
samples/ControlCatalog/Assets/Pulse/ex_deadlifts.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 342 KiB

BIN
samples/ControlCatalog/Assets/Pulse/ex_overhead.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 311 KiB

BIN
samples/ControlCatalog/Assets/Pulse/ex_pullups.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 253 KiB

BIN
samples/ControlCatalog/Assets/Pulse/ex_squats.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 341 KiB

BIN
samples/ControlCatalog/Assets/Pulse/profile_avatar.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 229 KiB

BIN
samples/ControlCatalog/Assets/Pulse/rec_fullbody.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 293 KiB

BIN
samples/ControlCatalog/Assets/Pulse/rec_mobility.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 370 KiB

BIN
samples/ControlCatalog/Assets/Pulse/rec_powercore.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 326 KiB

BIN
samples/ControlCatalog/Assets/Pulse/workout_hero.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 349 KiB

BIN
samples/ControlCatalog/Assets/Restaurant/dish1.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

BIN
samples/ControlCatalog/Assets/Restaurant/dish2.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

BIN
samples/ControlCatalog/Assets/Restaurant/dish3.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

BIN
samples/ControlCatalog/Assets/Restaurant/dish4.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

BIN
samples/ControlCatalog/Assets/Restaurant/featured_dish.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 67 KiB

BIN
samples/ControlCatalog/Assets/Restaurant/user_avatar.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

BIN
samples/ControlCatalog/Assets/RetroGaming/cyber_city.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 346 KiB

BIN
samples/ControlCatalog/Assets/RetroGaming/dungeon_bit.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 458 KiB

BIN
samples/ControlCatalog/Assets/RetroGaming/forest_spirit.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 416 KiB

BIN
samples/ControlCatalog/Assets/RetroGaming/hero.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 216 KiB

BIN
samples/ControlCatalog/Assets/RetroGaming/neon_ninja.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 296 KiB

BIN
samples/ControlCatalog/Assets/RetroGaming/neon_racer.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 389 KiB

BIN
samples/ControlCatalog/Assets/RetroGaming/pixel_quest.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 311 KiB

BIN
samples/ControlCatalog/Assets/RetroGaming/space_voids.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 338 KiB

6
samples/ControlCatalog/ControlCatalog.csproj

@ -13,6 +13,12 @@
</AvaloniaXaml>
<AvaloniaResource Include="Assets\*" />
<AvaloniaResource Include="Assets\Fonts\*" />
<AvaloniaResource Include="Assets\Restaurant\*" />
<AvaloniaResource Include="Assets\Pulse\*" />
<AvaloniaResource Include="Assets\Movies\*" />
<AvaloniaResource Include="Assets\CurvedHeader\*" />
<AvaloniaResource Include="Assets\RetroGaming\*" />
<AvaloniaResource Include="Assets\ModernApp\*" />
</ItemGroup>
<ItemGroup>
<None Remove="Assets\image1.jpg" />

10
samples/ControlCatalog/DecoratedWindow.xaml

@ -2,7 +2,7 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="ControlCatalog.DecoratedWindow"
Title="Avalonia Control Gallery"
SystemDecorations="None" Name="Window">
WindowDecorations="None" Name="Window">
<NativeMenu.Menu>
<NativeMenu>
<NativeMenuItem Header="Decorated">
@ -43,11 +43,11 @@
<StackPanel>
<TextBlock>Hello world!</TextBlock>
<ComboBox SelectedItem="{Binding ElementName=Window, Path=SystemDecorations}">
<ComboBox SelectedItem="{Binding ElementName=Window, Path=WindowDecorations}">
<ComboBox.Items>
<SystemDecorations>None</SystemDecorations>
<SystemDecorations>BorderOnly</SystemDecorations>
<SystemDecorations>Full</SystemDecorations>
<WindowDecorations>None</WindowDecorations>
<WindowDecorations>BorderOnly</WindowDecorations>
<WindowDecorations>Full</WindowDecorations>
</ComboBox.Items>
</ComboBox>
<CheckBox IsChecked="{Binding ElementName=Window, Path=CanResize}">CanResize</CheckBox>

32
samples/ControlCatalog/MainView.xaml

@ -49,9 +49,15 @@
<TabItem Header="Canvas">
<pages:CanvasPage />
</TabItem>
<TabItem Header="CommandBar"
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
ScrollViewer.VerticalScrollBarVisibility="Disabled">
<pages:CommandBarPage />
</TabItem>
<TabItem Header="Carousel">
<pages:CarouselPage />
</TabItem>
<TabItem Header="CheckBox">
<pages:CheckBoxPage />
</TabItem>
@ -67,6 +73,11 @@
<TabItem Header="Container Queries">
<pages:ContainerQueryPage />
</TabItem>
<TabItem Header="ContentPage"
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
ScrollViewer.VerticalScrollBarVisibility="Disabled">
<pages:ContentDemoPage />
</TabItem>
<TabItem Header="ContextFlyout">
<pages:ContextFlyoutPage />
</TabItem>
@ -99,6 +110,11 @@
<TabItem Header="Drag+Drop">
<pages:DragAndDropPage />
</TabItem>
<TabItem Header="DrawerPage"
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
ScrollViewer.VerticalScrollBarVisibility="Disabled">
<pages:DrawerDemoPage />
</TabItem>
<TabItem Header="Expander">
<pages:ExpanderPage />
</TabItem>
@ -128,6 +144,11 @@
<TabItem Header="Menu">
<pages:MenuPage />
</TabItem>
<TabItem Header="NavigationPage"
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
ScrollViewer.VerticalScrollBarVisibility="Disabled">
<pages:NavigationDemoPage />
</TabItem>
<TabItem Header="Notifications">
<pages:NotificationsPage />
</TabItem>
@ -167,6 +188,11 @@
<TabItem Header="SplitView">
<pages:SplitViewPage />
</TabItem>
<TabItem Header="TabbedPage"
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
ScrollViewer.VerticalScrollBarVisibility="Disabled">
<pages:TabbedDemoPage />
</TabItem>
<TabItem Header="TabControl">
<pages:TabControlPage />
</TabItem>
@ -218,9 +244,9 @@
SelectionChanged="Decorations_SelectionChanged"
ToolTip.Tip="System Decorations">
<ComboBox.Items>
<SystemDecorations>None</SystemDecorations>
<SystemDecorations>BorderOnly</SystemDecorations>
<SystemDecorations>Full</SystemDecorations>
<WindowDecorations>None</WindowDecorations>
<WindowDecorations>BorderOnly</WindowDecorations>
<WindowDecorations>Full</WindowDecorations>
</ComboBox.Items>
</ComboBox>
<ComboBox HorizontalAlignment="Stretch"

6
samples/ControlCatalog/MainView.xaml.cs

@ -45,9 +45,9 @@ namespace ControlCatalog
private void Decorations_SelectionChanged(object? sender, SelectionChangedEventArgs e)
{
if (TopLevel.GetTopLevel(this) is Window window && e.AddedItems.Count > 0 && e.AddedItems[0] is SystemDecorations systemDecorations)
if (TopLevel.GetTopLevel(this) is Window window && e.AddedItems.Count > 0 && e.AddedItems[0] is WindowDecorations systemDecorations)
{
window.SystemDecorations = systemDecorations;
window.WindowDecorations = systemDecorations;
}
}
@ -79,7 +79,7 @@ namespace ControlCatalog
base.OnAttachedToVisualTree(e);
if (TopLevel.GetTopLevel(this) is Window window)
Decorations.SelectedIndex = (int)window.SystemDecorations;
Decorations.SelectedIndex = (int)window.WindowDecorations;
var insets = TopLevel.GetTopLevel(this)!.InsetsManager;
if (insets != null)

1
samples/ControlCatalog/MainWindow.xaml

@ -8,7 +8,6 @@
xmlns:vm="clr-namespace:ControlCatalog.ViewModels;assembly=ControlCatalog"
xmlns:v="using:ControlCatalog.Views"
ExtendClientAreaToDecorationsHint="{Binding ExtendClientAreaEnabled}"
ExtendClientAreaChromeHints="{Binding ChromeHints}"
ExtendClientAreaTitleBarHeightHint="{Binding TitleBarHeight}"
CanResize="{Binding CanResize}"
CanMinimize="{Binding CanMinimize}"

120
samples/ControlCatalog/Pages/CommandBar/CommandBarCustomizationPage.xaml

@ -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>

90
samples/ControlCatalog/Pages/CommandBar/CommandBarCustomizationPage.xaml.cs

@ -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;
}
}
}

75
samples/ControlCatalog/Pages/CommandBar/CommandBarDynamicOverflowPage.xaml

@ -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>

45
samples/ControlCatalog/Pages/CommandBar/CommandBarDynamicOverflowPage.xaml.cs

@ -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";
}
}
}

94
samples/ControlCatalog/Pages/CommandBar/CommandBarFirstLookPage.xaml

@ -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>

27
samples/ControlCatalog/Pages/CommandBar/CommandBarFirstLookPage.xaml.cs

@ -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";
}
}
}

47
samples/ControlCatalog/Pages/CommandBar/CommandBarLabelPositionPage.xaml

@ -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>

12
samples/ControlCatalog/Pages/CommandBar/CommandBarLabelPositionPage.xaml.cs

@ -0,0 +1,12 @@
using Avalonia.Controls;
namespace ControlCatalog.Pages
{
public partial class CommandBarLabelPositionPage : UserControl
{
public CommandBarLabelPositionPage()
{
InitializeComponent();
}
}
}

74
samples/ControlCatalog/Pages/CommandBar/CommandBarOverflowPage.xaml

@ -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>

54
samples/ControlCatalog/Pages/CommandBar/CommandBarOverflowPage.xaml.cs

@ -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}" });
}
}
}

77
samples/ControlCatalog/Pages/CommandBar/CommandBarTogglePage.xaml

@ -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>

50
samples/ControlCatalog/Pages/CommandBar/CommandBarTogglePage.xaml.cs

@ -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;
}
}
}

8
samples/ControlCatalog/Pages/CommandBarPage.xaml

@ -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>

158
samples/ControlCatalog/Pages/CommandBarPage.xaml.cs

@ -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;
}
}
}

11
samples/ControlCatalog/Pages/ConnectedAnimationDemoPage.xaml

@ -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>

144
samples/ControlCatalog/Pages/ConnectedAnimationDemoPage.xaml.cs

@ -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;
}
}
}

11
samples/ControlCatalog/Pages/ContentDemoPage.xaml

@ -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>

160
samples/ControlCatalog/Pages/ContentDemoPage.xaml.cs

@ -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;
}
}
}

63
samples/ControlCatalog/Pages/ContentPage/ContentPageCommandBarPage.xaml

@ -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>

212
samples/ControlCatalog/Pages/ContentPage/ContentPageCommandBarPage.xaml.cs

@ -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})";
}
}
}

106
samples/ControlCatalog/Pages/ContentPage/ContentPageCustomizationPage.xaml

@ -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>

64
samples/ControlCatalog/Pages/ContentPage/ContentPageCustomizationPage.xaml.cs

@ -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";
}
}
}

66
samples/ControlCatalog/Pages/ContentPage/ContentPageEventsPage.xaml

@ -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>

103
samples/ControlCatalog/Pages/ContentPage/ContentPageEventsPage.xaml.cs

@ -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,
};
}
}

48
samples/ControlCatalog/Pages/ContentPage/ContentPageFirstLookPage.xaml

@ -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>

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save