Browse Source

ControlCatalog: add dashboard home page with animated hero and nav cards

A new Home page (first in the drawer) modeled on the Accelerate demo
dashboard: a gradient hero banner with floating control glyphs animated
via keyframed TranslateTransforms, followed by categorized card sections
for every catalog page. Cards carry an icon badge, title and one-line
description, and clicking one navigates via SelectedPageIndex so the
drawer selection stays in sync. PageItem gains Description/Category and
the view model exposes grouped HomeSections plus NavigateToPageCommand.
Card colors are self-contained theme dictionaries so the page works
across Fluent/Fluent2/Simple in both variants.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
pull/21771/head
Mike James 3 months ago
parent
commit
94f7bc7196
  1. 3
      samples/ControlCatalog/Icons.cs
  2. 174
      samples/ControlCatalog/Pages/HomePage.xaml
  3. 78
      samples/ControlCatalog/Pages/HomePage.xaml.cs
  4. 3
      samples/ControlCatalog/ViewModels/MainWindowViewModel.cs
  5. 186
      samples/ControlCatalog/ViewModels/MainWindowViewModel_PageList.cs

3
samples/ControlCatalog/Icons.cs

@ -190,5 +190,8 @@ namespace ControlCatalog
// Slider tune/adjust
public const string Tune = "M3,17V19H9V17H3M3,5V7H13V5H3M13,21V19H21V17H13V15H11V21H13M7,9V11H3V13H7V15H9V9H7M21,13V11H11V13H21M15,9H17V7H21V5H17V3H15V9Z";
// Home
public const string Home = "M10,20V14H14V20H19V12H22L12,3L2,12H5V20H10Z";
}
}

174
samples/ControlCatalog/Pages/HomePage.xaml

@ -0,0 +1,174 @@
<ContentPage Theme="{StaticResource ScrollPage}"
xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:ControlCatalog"
xmlns:viewModels="using:ControlCatalog.ViewModels"
x:Class="ControlCatalog.Pages.HomePage"
x:DataType="viewModels:MainWindowViewModel"
Header="Home">
<ContentPage.Resources>
<ResourceDictionary>
<ResourceDictionary.ThemeDictionaries>
<ResourceDictionary x:Key="Default">
<SolidColorBrush x:Key="HomeCardBackground" Color="#FFFFFF" />
<SolidColorBrush x:Key="HomeCardBorderBrush" Color="#E5E5EA" />
<SolidColorBrush x:Key="HomeCardBorderBrushHover" Color="#3E6DF3" />
<SolidColorBrush x:Key="HomeSubtleForeground" Color="#64646E" />
<SolidColorBrush x:Key="HomeBadgeBackground" Color="#E8EFFD" />
<SolidColorBrush x:Key="HomeBadgeForeground" Color="#3462D9" />
<SolidColorBrush x:Key="HomeSectionDivider" Color="#EBEBEF" />
</ResourceDictionary>
<ResourceDictionary x:Key="Dark">
<SolidColorBrush x:Key="HomeCardBackground" Color="#2B2B33" />
<SolidColorBrush x:Key="HomeCardBorderBrush" Color="#3A3A45" />
<SolidColorBrush x:Key="HomeCardBorderBrushHover" Color="#8AB4FF" />
<SolidColorBrush x:Key="HomeSubtleForeground" Color="#9C9CAB" />
<SolidColorBrush x:Key="HomeBadgeBackground" Color="#31395A" />
<SolidColorBrush x:Key="HomeBadgeForeground" Color="#8AB4FF" />
<SolidColorBrush x:Key="HomeSectionDivider" Color="#3A3A45" />
</ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>
</ResourceDictionary>
</ContentPage.Resources>
<ContentPage.Styles>
<!-- Neutralize the themed Button chrome so only the inner card Border shows. -->
<Style Selector="Button.card /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="Background" Value="Transparent" />
<Setter Property="BorderBrush" Value="Transparent" />
</Style>
<Style Selector="Button.card:pointerover /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="Background" Value="Transparent" />
<Setter Property="BorderBrush" Value="Transparent" />
</Style>
<Style Selector="Button.card:pressed /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="Background" Value="Transparent" />
<Setter Property="BorderBrush" Value="Transparent" />
</Style>
<Style Selector="Button.card > Border">
<Setter Property="Transitions">
<Transitions>
<BrushTransition Property="BorderBrush" Duration="0:0:0.1" />
</Transitions>
</Setter>
</Style>
<Style Selector="Button.card:pointerover > Border">
<Setter Property="BorderBrush" Value="{DynamicResource HomeCardBorderBrushHover}" />
</Style>
</ContentPage.Styles>
<StackPanel Spacing="28" Margin="0,0,15,20" HorizontalAlignment="Stretch">
<!-- Hero banner -->
<Border CornerRadius="16" ClipToBounds="True" Height="220" HorizontalAlignment="Stretch">
<Border.Background>
<LinearGradientBrush StartPoint="0%,0%" EndPoint="100%,100%">
<GradientStop Offset="0" Color="#6D28D9" />
<GradientStop Offset="0.55" Color="#4338CA" />
<GradientStop Offset="1" Color="#2563EB" />
</LinearGradientBrush>
</Border.Background>
<Grid ClipToBounds="True">
<!-- Floating control glyphs, animated from code-behind -->
<Canvas IsHitTestVisible="False">
<PathIcon x:Name="FloatIcon1"
Data="{x:Static local:Icons.CursorClick}"
Foreground="#26FFFFFF"
Width="120" Height="120"
Canvas.Left="-30" Canvas.Bottom="-25" />
<PathIcon x:Name="FloatIcon2"
Data="{x:Static local:Icons.Palette}"
Foreground="#21FFFFFF"
Width="96" Height="96"
Canvas.Left="200" Canvas.Top="-30" />
<PathIcon x:Name="FloatIcon3"
Data="{x:Static local:Icons.Calendar}"
Foreground="#26FFFFFF"
Width="110" Height="110"
Canvas.Right="-25" Canvas.Top="-20" />
<PathIcon x:Name="FloatIcon4"
Data="{x:Static local:Icons.Toggle}"
Foreground="#21FFFFFF"
Width="130" Height="130"
Canvas.Right="170" Canvas.Bottom="-40" />
</Canvas>
<!-- Centered lockup -->
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center" Spacing="10">
<Image Source="/Assets/Icon.png" Height="64" />
<TextBlock Text="Avalonia Control Catalog"
FontSize="26" FontWeight="Bold"
Foreground="White"
HorizontalAlignment="Center" />
<TextBlock Text="Explore every control, on every platform, in every theme"
FontSize="13"
Foreground="#B3FFFFFF"
HorizontalAlignment="Center" />
</StackPanel>
</Grid>
</Border>
<!-- Card sections -->
<ItemsControl ItemsSource="{Binding HomeSections}">
<ItemsControl.ItemTemplate>
<DataTemplate DataType="viewModels:HomeSection">
<StackPanel Spacing="14" Margin="0,0,0,26">
<TextBlock Text="{Binding Title}"
FontSize="19" FontWeight="Bold" />
<ItemsControl ItemsSource="{Binding Items}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate DataType="viewModels:PageItem">
<Button Classes="card"
Command="{Binding $parent[ContentPage].((viewModels:MainWindowViewModel)DataContext).NavigateToPageCommand}"
CommandParameter="{Binding}"
Margin="0,0,12,12"
Padding="0"
Background="Transparent"
BorderThickness="0"
Cursor="Hand">
<Border Background="{DynamicResource HomeCardBackground}"
BorderBrush="{DynamicResource HomeCardBorderBrush}"
BorderThickness="1"
CornerRadius="10"
Padding="16,14"
Width="248"
MinHeight="118"
BoxShadow="0 1 3 0 #0D000000">
<StackPanel Spacing="10">
<Border Background="{DynamicResource HomeBadgeBackground}"
CornerRadius="8"
Width="36" Height="36"
HorizontalAlignment="Left">
<PathIcon Data="{Binding IconData}"
Foreground="{DynamicResource HomeBadgeForeground}"
Width="18" Height="18"
HorizontalAlignment="Center"
VerticalAlignment="Center" />
</Border>
<StackPanel Spacing="3">
<TextBlock Text="{Binding Header}"
FontSize="14" FontWeight="SemiBold" />
<TextBlock Text="{Binding Description}"
FontSize="12"
Foreground="{DynamicResource HomeSubtleForeground}"
TextWrapping="Wrap"
MaxLines="2" />
</StackPanel>
</StackPanel>
</Border>
</Button>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</ContentPage>

78
samples/ControlCatalog/Pages/HomePage.xaml.cs

@ -0,0 +1,78 @@
using System;
using Avalonia;
using Avalonia.Animation;
using Avalonia.Controls;
using Avalonia.Media;
using Avalonia.Styling;
using Avalonia.VisualTree;
using ControlCatalog.ViewModels;
namespace ControlCatalog.Pages
{
public partial class HomePage : ContentPage
{
public HomePage()
{
InitializeComponent();
}
protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
{
base.OnAttachedToVisualTree(e);
// Pages hosted in a NavigationPage inherit the navigator as DataContext;
// the card grid binds to MainWindowViewModel, so resolve it from MainView.
if (DataContext is not MainWindowViewModel)
DataContext = this.FindAncestorOfType<MainView>()?.DataContext;
StartFloatingAnimation(FloatIcon1, 12, 8, TimeSpan.FromSeconds(12));
StartFloatingAnimation(FloatIcon2, -14, 8, TimeSpan.FromSeconds(10));
StartFloatingAnimation(FloatIcon3, -12, -12, TimeSpan.FromSeconds(14));
StartFloatingAnimation(FloatIcon4, 12, -8, TimeSpan.FromSeconds(11));
}
private static void StartFloatingAnimation(Control target, double dx, double dy, TimeSpan duration)
{
var transform = new TranslateTransform();
target.RenderTransform = transform;
var animation = new Animation
{
Duration = duration,
IterationCount = IterationCount.Infinite,
Children =
{
new KeyFrame
{
Cue = new Cue(0d),
Setters =
{
new Setter(TranslateTransform.XProperty, 0d),
new Setter(TranslateTransform.YProperty, 0d),
}
},
new KeyFrame
{
Cue = new Cue(0.5d),
Setters =
{
new Setter(TranslateTransform.XProperty, dx),
new Setter(TranslateTransform.YProperty, dy),
}
},
new KeyFrame
{
Cue = new Cue(1d),
Setters =
{
new Setter(TranslateTransform.XProperty, 0d),
new Setter(TranslateTransform.YProperty, 0d),
}
},
}
};
_ = animation.RunAsync(target);
}
}
}

3
samples/ControlCatalog/ViewModels/MainWindowViewModel.cs

@ -37,6 +37,7 @@ namespace ControlCatalog.ViewModels
{
(App.Current?.ApplicationLifetime as IClassicDesktopStyleApplicationLifetime)?.Shutdown();
});
NavigateToPageCommand = MiniCommand.Create<PageItem>(NavigateToPage);
WindowState = WindowState.Normal;
@ -127,6 +128,8 @@ namespace ControlCatalog.ViewModels
public MiniCommand ExitCommand { get; }
public MiniCommand NavigateToPageCommand { get; }
private DateTime? _validatedDateExample;
/// <summary>

186
samples/ControlCatalog/ViewModels/MainWindowViewModel_PageList.cs

@ -26,78 +26,114 @@ namespace ControlCatalog.ViewModels
private List<PageItem> _items = new()
{
new PageItem("Composition", () => new CompositionPage(), Icons.Layers),
new PageItem("Accelerator", () => new AcceleratorPage(), Icons.Keyboard),
new PageItem("Acrylic", () => new AcrylicPage(), Icons.Blur),
new PageItem("AdornerLayer", () => new AdornerLayerPage(), Icons.Sparkle),
new PageItem("AutoCompleteBox",() => new AutoCompleteBoxPage(), Icons.TextInput),
new PageItem("Border",() => new BorderPage(), Icons.Border),
new PageItem("BitmapCache",() => new BitmapCachePage(), Icons.Lightning),
new PageItem("Buttons",() => new ButtonsPage(), Icons.CursorClick),
new PageItem("ButtonSpinner",() => new ButtonSpinnerPage(), Icons.Spinner),
new PageItem("Calendar",() => new CalendarPage(), Icons.Calendar),
new PageItem("Canvas",() => new CanvasPage(), Icons.Canvas),
new PageItem("CommandBar",() => new CommandBarPage(), Icons.Terminal),
new PageItem("Carousel",() => new Pages.CarouselPage(), Icons.Slides),
new PageItem("CarouselPage",() => new CarouselDemoPage(), Icons.Slides),
new PageItem("CheckBox",() => new CheckBoxPage(), Icons.Checkbox),
new PageItem("Clipboard",() => new ClipboardPage(), Icons.Clipboard),
new PageItem("ColorPicker",() => new ColorPickerPage(), Icons.Palette),
new PageItem("ComboBox",() => new ComboBoxPage(), Icons.Dropdown),
new PageItem("Container Queries",() => new ContainerQueryPage(), Icons.Container),
new PageItem("ContentPage",() => new ContentDemoPage(), Icons.Document),
new PageItem("ContextFlyout",() => new ContextFlyoutPage(), Icons.Menu),
new PageItem("ContextMenu",() => new ContextMenuPage(), Icons.Menu),
new PageItem("Cursor",() => new CursorPage(), Icons.Cursor),
new PageItem("Custom Drawing",() => new CustomDrawing(), Icons.Brush),
new PageItem("DataGrid",() => new DataGridPage(), Icons.Grid),
new PageItem("Data Validation",() => new DataValidationPage(), Icons.Shield),
new PageItem("Date/Time Picker",() => new DateTimePickerPage(), Icons.Clock),
new PageItem("CalendarDatePicker",() => new CalendarDatePickerPage(), Icons.Calendar),
new PageItem("Dialogs",() => new DialogsPage(), Icons.Dialog),
new PageItem("Drag+Drop",() => new DragAndDropPage(), Icons.DragDrop),
new PageItem("DrawerPage",() => new DrawerDemoPage(), Icons.Drawer),
new PageItem("Expander",() => new ExpanderPage(), Icons.Expand),
new PageItem("Flyouts",() => new FlyoutsPage(), Icons.Flyout),
new PageItem("Focus",() => new FocusPage(), Icons.Target),
new PageItem("Gestures",() => new GesturePage(), Icons.Gesture),
new PageItem("Image",() => new ImagePage(), Icons.Image),
new PageItem("Label",() => new LabelsPage(), Icons.Tag),
new PageItem("LayoutTransformControl",() => new LayoutTransformControlPage(), Icons.Transform),
new PageItem("ListBox",() => new ListBoxPage(), Icons.List),
new PageItem("Menu",() => new MenuPage(), Icons.Menu),
new PageItem("NavigationPage",() => new NavigationDemoPage(), Icons.Navigation),
new PageItem("Notifications",() => new NotificationsPage(), Icons.Bell),
new PageItem("NumericUpDown",() => new NumericUpDownPage(), Icons.Number),
new PageItem("OpenGL",() => new OpenGlPage(), Icons.Cube3D),
new PageItem("OpenGL Lease",() => new OpenGlLeasePage(), Icons.Cube3D),
new PageItem("PipsPager",() => new PipsPagerPage(), Icons.HorizontalDots),
new PageItem("Platform Information",() => new PlatformInfoPage(), Icons.Info),
new PageItem("Pointers",() => new PointersPage(), Icons.Cursor),
new PageItem("ProgressBar",() => new ProgressBarPage(), Icons.Progress),
new PageItem("RadioButton",() => new RadioButtonPage(), Icons.Radio),
new PageItem("RefreshContainer",() => new RefreshContainerPage(), Icons.Refresh),
new PageItem("RelativePanel",() => new RelativePanelPage(), Icons.Layout),
new PageItem("ScrollViewer",() => new ScrollViewerPage(), Icons.Scroll),
new PageItem("Slider",() => new SliderPage(), Icons.Tune),
new PageItem("SplitView",() => new SplitViewPage(), Icons.Split),
new PageItem("TabbedPage",() => new TabbedDemoPage(), Icons.Tab),
new PageItem("TabControl",() => new TabControlPage(), Icons.Tab),
new PageItem("TabStrip",() => new TabStripPage(), Icons.Tab),
new PageItem("TextBox",() => new TextBoxPage(), Icons.TextInput),
new PageItem("TextBlock",() => new TextBlockPage(), Icons.TextInput),
new PageItem("Theme Variants",() => new ThemePage(), Icons.Theme),
new PageItem("ToggleSwitch",() => new ToggleSwitchPage(), Icons.Toggle),
new PageItem("ToolTip",() => new ToolTipPage(), Icons.Tooltip),
new PageItem("TransitioningContentControl",() => new TransitioningContentControlPage(), Icons.Transition),
new PageItem("TreeView",() => new TreeViewPage(), Icons.Tree),
new PageItem("Viewbox",() => new ViewboxPage(), Icons.Viewbox),
new PageItem("Native Embed",() => new NativeEmbedPage(), Icons.Puzzle),
new PageItem("Window Customizations",() => new WindowCustomizationsPage(), Icons.Window),
new PageItem("HeaderedContentControl",() => new HeaderedContentPage(), Icons.Header),
new PageItem("Screens",() => new ScreenPage(), Icons.Monitor),
new PageItem("Home", () => new HomePage(), Icons.Home, "Overview of everything in the catalog"),
new PageItem("Composition", () => new CompositionPage(), Icons.Layers, "Composition-layer animations and effects", "Media & Graphics"),
new PageItem("Accelerator", () => new AcceleratorPage(), Icons.Keyboard, "Keyboard shortcuts that invoke commands", "Interaction"),
new PageItem("Acrylic", () => new AcrylicPage(), Icons.Blur, "Translucent acrylic window materials", "Media & Graphics"),
new PageItem("AdornerLayer", () => new AdornerLayerPage(), Icons.Sparkle, "Overlay visuals on top of other controls", "Status & Feedback"),
new PageItem("AutoCompleteBox",() => new AutoCompleteBoxPage(), Icons.TextInput, "Text input with completion suggestions", "Text"),
new PageItem("Border",() => new BorderPage(), Icons.Border, "Decorate elements with borders and corner radii", "Layout"),
new PageItem("BitmapCache",() => new BitmapCachePage(), Icons.Lightning, "Cache visuals as bitmaps for performance", "Media & Graphics"),
new PageItem("Buttons",() => new ButtonsPage(), Icons.CursorClick, "Button, RepeatButton, ToggleButton and friends", "Basic Input"),
new PageItem("ButtonSpinner",() => new ButtonSpinnerPage(), Icons.Spinner, "Content with increment and decrement buttons", "Basic Input"),
new PageItem("Calendar",() => new CalendarPage(), Icons.Calendar, "A month calendar for selecting dates", "Date & Time"),
new PageItem("Canvas",() => new CanvasPage(), Icons.Canvas, "Position children at explicit coordinates", "Layout"),
new PageItem("CommandBar",() => new CommandBarPage(), Icons.Terminal, "A toolbar of commands with an overflow menu", "Menus & Flyouts"),
new PageItem("Carousel",() => new Pages.CarouselPage(), Icons.Slides, "Cycle through a collection of items", "Collections & Data"),
new PageItem("CarouselPage",() => new CarouselDemoPage(), Icons.Slides, "Swipeable page-based navigation", "Navigation & Pages"),
new PageItem("CheckBox",() => new CheckBoxPage(), Icons.Checkbox, "Two- and three-state check boxes", "Basic Input"),
new PageItem("Clipboard",() => new ClipboardPage(), Icons.Clipboard, "Read from and write to the system clipboard", "Interaction"),
new PageItem("ColorPicker",() => new ColorPickerPage(), Icons.Palette, "Pick colors from spectrum and palette views", "Basic Input"),
new PageItem("ComboBox",() => new ComboBoxPage(), Icons.Dropdown, "A drop-down list of selectable items", "Basic Input"),
new PageItem("Container Queries",() => new ContainerQueryPage(), Icons.Container, "Styles that respond to container size", "Layout"),
new PageItem("ContentPage",() => new ContentDemoPage(), Icons.Document, "A page that hosts a single content view", "Navigation & Pages"),
new PageItem("ContextFlyout",() => new ContextFlyoutPage(), Icons.Menu, "Attach flyouts shown on right-click", "Menus & Flyouts"),
new PageItem("ContextMenu",() => new ContextMenuPage(), Icons.Menu, "Traditional right-click context menus", "Menus & Flyouts"),
new PageItem("Cursor",() => new CursorPage(), Icons.Cursor, "Change the pointer cursor over elements", "Interaction"),
new PageItem("Custom Drawing",() => new CustomDrawing(), Icons.Brush, "Render custom geometry in code", "Media & Graphics"),
new PageItem("DataGrid",() => new DataGridPage(), Icons.Grid, "Tabular data with sorting and editing", "Collections & Data"),
new PageItem("Data Validation",() => new DataValidationPage(), Icons.Shield, "Display validation errors from bindings", "Status & Feedback"),
new PageItem("Date/Time Picker",() => new DateTimePickerPage(), Icons.Clock, "Spinner-style date and time pickers", "Date & Time"),
new PageItem("CalendarDatePicker",() => new CalendarDatePickerPage(), Icons.Calendar, "A date picker with a drop-down calendar", "Date & Time"),
new PageItem("Dialogs",() => new DialogsPage(), Icons.Dialog, "File pickers and modal dialog windows", "Status & Feedback"),
new PageItem("Drag+Drop",() => new DragAndDropPage(), Icons.DragDrop, "Drag data within and between applications", "Interaction"),
new PageItem("DrawerPage",() => new DrawerDemoPage(), Icons.Drawer, "A page with a sliding navigation drawer", "Navigation & Pages"),
new PageItem("Expander",() => new ExpanderPage(), Icons.Expand, "A header that expands to reveal content", "Layout"),
new PageItem("Flyouts",() => new FlyoutsPage(), Icons.Flyout, "Lightweight popups anchored to controls", "Menus & Flyouts"),
new PageItem("Focus",() => new FocusPage(), Icons.Target, "Track and control keyboard focus", "Interaction"),
new PageItem("Gestures",() => new GesturePage(), Icons.Gesture, "Tap, scroll and pinch gesture recognition", "Interaction"),
new PageItem("Image",() => new ImagePage(), Icons.Image, "Display bitmaps with different stretch modes", "Media & Graphics"),
new PageItem("Label",() => new LabelsPage(), Icons.Tag, "Captions with access keys for other controls", "Text"),
new PageItem("LayoutTransformControl",() => new LayoutTransformControlPage(), Icons.Transform, "Apply transforms that affect layout", "Layout"),
new PageItem("ListBox",() => new ListBoxPage(), Icons.List, "A selectable, virtualized list of items", "Collections & Data"),
new PageItem("Menu",() => new MenuPage(), Icons.Menu, "Menu bars with nested menu items", "Menus & Flyouts"),
new PageItem("NavigationPage",() => new NavigationDemoPage(), Icons.Navigation, "Stack-based page navigation", "Navigation & Pages"),
new PageItem("Notifications",() => new NotificationsPage(), Icons.Bell, "Toast-style in-app notifications", "Status & Feedback"),
new PageItem("NumericUpDown",() => new NumericUpDownPage(), Icons.Number, "Numeric input with spinner buttons", "Basic Input"),
new PageItem("OpenGL",() => new OpenGlPage(), Icons.Cube3D, "Embed custom OpenGL rendering", "Media & Graphics"),
new PageItem("OpenGL Lease",() => new OpenGlLeasePage(), Icons.Cube3D, "Low-level access to the OpenGL context", "Media & Graphics"),
new PageItem("PipsPager",() => new PipsPagerPage(), Icons.HorizontalDots, "Dot-style pager for paginated content", "Collections & Data"),
new PageItem("Platform Information",() => new PlatformInfoPage(), Icons.Info, "Runtime platform and capability info", "Window & Platform"),
new PageItem("Pointers",() => new PointersPage(), Icons.Cursor, "Raw pointer input and capture", "Interaction"),
new PageItem("ProgressBar",() => new ProgressBarPage(), Icons.Progress, "Determinate and indeterminate progress", "Status & Feedback"),
new PageItem("RadioButton",() => new RadioButtonPage(), Icons.Radio, "Mutually exclusive option groups", "Basic Input"),
new PageItem("RefreshContainer",() => new RefreshContainerPage(), Icons.Refresh, "Pull-to-refresh for scrollable content", "Collections & Data"),
new PageItem("RelativePanel",() => new RelativePanelPage(), Icons.Layout, "Arrange children relative to each other", "Layout"),
new PageItem("ScrollViewer",() => new ScrollViewerPage(), Icons.Scroll, "Scrollable viewport over large content", "Layout"),
new PageItem("Slider",() => new SliderPage(), Icons.Tune, "Select a value from a continuous range", "Basic Input"),
new PageItem("SplitView",() => new SplitViewPage(), Icons.Split, "A collapsible pane beside content", "Navigation & Pages"),
new PageItem("TabbedPage",() => new TabbedDemoPage(), Icons.Tab, "Tab-based page navigation", "Navigation & Pages"),
new PageItem("TabControl",() => new TabControlPage(), Icons.Tab, "Switch between tabbed content views", "Navigation & Pages"),
new PageItem("TabStrip",() => new TabStripPage(), Icons.Tab, "A standalone strip of selectable tabs", "Navigation & Pages"),
new PageItem("TextBox",() => new TextBoxPage(), Icons.TextInput, "Single- and multi-line text editing", "Text"),
new PageItem("TextBlock",() => new TextBlockPage(), Icons.TextInput, "Styled read-only text display", "Text"),
new PageItem("Theme Variants",() => new ThemePage(), Icons.Theme, "Switch between light and dark variants", "Window & Platform"),
new PageItem("ToggleSwitch",() => new ToggleSwitchPage(), Icons.Toggle, "An on/off switch with a sliding knob", "Basic Input"),
new PageItem("ToolTip",() => new ToolTipPage(), Icons.Tooltip, "Hover hints for any control", "Status & Feedback"),
new PageItem("TransitioningContentControl",() => new TransitioningContentControlPage(), Icons.Transition, "Animate between content changes", "Media & Graphics"),
new PageItem("TreeView",() => new TreeViewPage(), Icons.Tree, "Hierarchical data with expandable nodes", "Collections & Data"),
new PageItem("Viewbox",() => new ViewboxPage(), Icons.Viewbox, "Scale content to fit available space", "Layout"),
new PageItem("Native Embed",() => new NativeEmbedPage(), Icons.Puzzle, "Host native platform controls", "Window & Platform"),
new PageItem("Window Customizations",() => new WindowCustomizationsPage(), Icons.Window, "Custom chrome, decorations and sizing", "Window & Platform"),
new PageItem("HeaderedContentControl",() => new HeaderedContentPage(), Icons.Header, "Content paired with a header", "Layout"),
new PageItem("Screens",() => new ScreenPage(), Icons.Monitor, "Enumerate displays and their bounds", "Window & Platform"),
};
/// <summary>Section order for the home page card grid.</summary>
private static readonly string[] s_categoryOrder =
{
"Basic Input",
"Text",
"Collections & Data",
"Date & Time",
"Menus & Flyouts",
"Navigation & Pages",
"Layout",
"Media & Graphics",
"Status & Feedback",
"Interaction",
"Window & Platform",
};
private IReadOnlyList<HomeSection>? _homeSections;
public IReadOnlyList<HomeSection> HomeSections => _homeSections ??=
s_categoryOrder
.Select(category => new HomeSection(category, _items.Where(i => i.Category == category).ToArray()))
.Where(section => section.Items.Count > 0)
.ToArray();
public void NavigateToPage(PageItem item)
{
// Clear any active search so the target is present in the filtered list.
if (!string.IsNullOrEmpty(Query))
Query = "";
var index = Pages.IndexOf(item);
if (index >= 0)
SelectedPageIndex = index;
}
public AvaloniaList<PageItem> Pages { get; } = new AvaloniaList<PageItem>();
public void Filter(string? query = "")
@ -206,11 +242,19 @@ namespace ControlCatalog.ViewModels
}
}
class PageItem(string header, Func<object> factory, string? iconData = null)
class HomeSection(string title, IReadOnlyList<PageItem> items)
{
public string Title { get; } = title;
public IReadOnlyList<PageItem> Items { get; } = items;
}
class PageItem(string header, Func<object> factory, string? iconData = null, string? description = null, string? category = null)
{
public string Header { get; } = header;
public Func<object> Factory { get; } = factory;
public string? IconData { get; } = iconData;
public string? Description { get; } = description;
public string? Category { get; } = category;
private string SearchKey { get; } = CreateSearchKey(header);
public bool IsVisible { get; set; } = true;

Loading…
Cancel
Save