Merge pull request #718 from irihitech/anchor

New Control: Anchor
This commit is contained in:
Zhang Dian
2025-07-10 20:51:35 +08:00
committed by GitHub
27 changed files with 1098 additions and 30 deletions

View File

@@ -0,0 +1,265 @@
<UserControl
x:Class="Ursa.Demo.Pages.AnchorDemo"
xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:u="https://irihi.tech/ursa"
xmlns:viewModels="clr-namespace:Ursa.Demo.ViewModels"
d:DesignHeight="450"
d:DesignWidth="800"
x:DataType="viewModels:AnchorDemoViewModel"
mc:Ignorable="d">
<TabControl>
<TabItem Header="XAML Inline">
<Grid ColumnDefinitions="*, Auto">
<ScrollViewer
Name="container1"
Grid.Column="0"
VerticalAlignment="Stretch">
<StackPanel>
<StackPanel.Styles>
<Style Selector="TextBlock">
<Setter Property="HorizontalAlignment" Value="Center" />
<Setter Property="VerticalAlignment" Value="Center" />
</Style>
</StackPanel.Styles>
<Border
u:Anchor.Id="a1"
Height="300"
HorizontalAlignment="Stretch"
Background="{DynamicResource SemiRed2}">
<TextBlock Text="Border 1" />
</Border>
<Border
u:Anchor.Id="a2"
Height="300"
HorizontalAlignment="Stretch"
Background="{DynamicResource SemiPink1}">
<TextBlock Text="Border 2" />
</Border>
<Border
u:Anchor.Id="a3"
Height="300"
HorizontalAlignment="Stretch"
Background="{DynamicResource SemiPurple1}">
<TextBlock Text="Border 3" />
</Border>
<Border
Height="300"
HorizontalAlignment="Stretch"
Background="{DynamicResource SemiViolet1}">
<TextBlock u:Anchor.Id="a4" Text="Border 4" />
</Border>
<Border
u:Anchor.Id="a5"
Height="300"
HorizontalAlignment="Stretch"
Background="{DynamicResource SemiIndigo1}">
<TextBlock Text="Border 5" />
</Border>
<Border
u:Anchor.Id="a6"
Height="300"
HorizontalAlignment="Stretch"
Background="{DynamicResource SemiBlue1}">
<TextBlock Text="Border 6" />
</Border>
<Border
u:Anchor.Id="a7"
Height="300"
HorizontalAlignment="Stretch"
Background="{DynamicResource SemiLightBlue1}">
<TextBlock Text="Border 7" />
</Border>
</StackPanel>
</ScrollViewer>
<u:Anchor
Grid.Column="1"
Width="200"
Margin="24"
TargetContainer="{Binding ElementName=container1}">
<u:AnchorItem Header="Rectangle 1" AnchorId="a1">
<u:AnchorItem Header="Rectangle 2" AnchorId="a2" />
<u:AnchorItem Header="Rectangle 3" AnchorId="a3" />
</u:AnchorItem>
<u:AnchorItem Header="Rectangle 4" AnchorId="a4" />
<u:AnchorItem Header="Rectangle 5" AnchorId="a5">
<u:AnchorItem Header="Rectangle 6" AnchorId="a6" />
<u:AnchorItem Header="Rectangle 7" AnchorId="a7" />
</u:AnchorItem>
</u:Anchor>
</Grid>
</TabItem>
<TabItem Header="MVVM">
<Grid ColumnDefinitions="*, Auto">
<ScrollViewer
Name="container2"
Grid.Column="0"
VerticalAlignment="Stretch">
<StackPanel>
<StackPanel.Styles>
<Style Selector="TextBlock">
<Setter Property="HorizontalAlignment" Value="Center" />
<Setter Property="VerticalAlignment" Value="Center" />
</Style>
</StackPanel.Styles>
<Border
Height="300"
HorizontalAlignment="Stretch"
u:Anchor.Id="anchor1"
Background="{DynamicResource SemiRed2}">
<TextBlock Text="Border 1" />
</Border>
<Border
Height="300"
HorizontalAlignment="Stretch"
u:Anchor.Id="anchor2"
Background="{DynamicResource SemiPink1}">
<TextBlock Text="Border 2" />
</Border>
<Border
Height="300"
HorizontalAlignment="Stretch"
u:Anchor.Id="anchor3"
Background="{DynamicResource SemiPurple1}">
<TextBlock Text="Border 3" />
</Border>
<Border
Height="300"
HorizontalAlignment="Stretch"
u:Anchor.Id="anchor3-1"
Background="{DynamicResource SemiPurple1}">
<TextBlock Text="Border 3-1" />
</Border>
<Border
Height="300"
HorizontalAlignment="Stretch"
u:Anchor.Id="anchor3-2"
Background="{DynamicResource SemiPurple1}">
<TextBlock Text="Border 3-2" />
</Border>
<Border
Height="300"
HorizontalAlignment="Stretch"
u:Anchor.Id="anchor3-2-1"
Background="{DynamicResource SemiCyan1}">
<TextBlock Text="Border 3-2-1" />
</Border>
<Border
Height="300"
HorizontalAlignment="Stretch"
u:Anchor.Id="anchor3-2-2"
Background="{DynamicResource SemiCyan1}">
<TextBlock Text="Border 3-2-2" />
</Border>
<Border
Height="300"
HorizontalAlignment="Stretch"
u:Anchor.Id="anchor3-2-3"
Background="{DynamicResource SemiCyan1}">
<TextBlock Text="Border 3-2-3" />
</Border>
<Border
Height="300"
HorizontalAlignment="Stretch"
u:Anchor.Id="anchor3-3"
Background="{DynamicResource SemiPurple1}">
<TextBlock Text="Border 3-3" />
</Border>
<Border
Height="300"
HorizontalAlignment="Stretch"
u:Anchor.Id="anchor4"
Background="{DynamicResource SemiViolet1}">
<TextBlock Text="Border 4" />
</Border>
<Border
Height="300"
HorizontalAlignment="Stretch"
u:Anchor.Id="anchor5"
Background="{DynamicResource SemiIndigo1}">
<TextBlock Text="Border 5" />
</Border>
<Border
Height="300"
HorizontalAlignment="Stretch"
u:Anchor.Id="anchor6"
Background="{DynamicResource SemiBlue1}">
<TextBlock Text="Border 6" />
</Border>
<Border
Height="300"
HorizontalAlignment="Stretch"
u:Anchor.Id="anchor7"
Background="{DynamicResource SemiLightBlue1}">
<TextBlock Text="Border 7" />
</Border>
</StackPanel>
</ScrollViewer>
<u:Anchor
Grid.Column="1"
Width="200"
Margin="24"
ItemsSource="{Binding AnchorItems}"
TargetContainer="{Binding #container2}">
<u:Anchor.Styles>
<Style x:DataType="viewModels:AnchorItemViewModel" Selector="u|AnchorItem">
<Setter Property="AnchorId" Value="{Binding AnchorId}" />
</Style>
</u:Anchor.Styles>
<u:Anchor.ItemTemplate>
<TreeDataTemplate ItemsSource="{Binding Children}">
<TextBlock Text="{Binding Header}" />
</TreeDataTemplate>
</u:Anchor.ItemTemplate>
</u:Anchor>
</Grid>
</TabItem>
<TabItem Header="Appearance">
<StackPanel
Orientation="Horizontal"
Spacing="100"
Margin="8">
<u:Anchor>
<u:AnchorItem Header="组件" />
<u:AnchorItem Header="设计语言" />
<u:AnchorItem Header="物料平台" />
<u:AnchorItem Header="主题商店" />
</u:Anchor>
<u:Anchor Classes="Small">
<u:AnchorItem Header="组件" />
<u:AnchorItem Header="设计语言" />
<u:AnchorItem Header="物料平台" />
<u:AnchorItem Header="主题商店" />
</u:Anchor>
<u:Anchor Classes="Tertiary">
<u:AnchorItem Header="尺寸" />
<u:AnchorItem Header="组件" />
<u:AnchorItem Header="设计语言" />
<u:AnchorItem Header="物料平台" />
<u:AnchorItem Header="主题商店" />
</u:Anchor>
<u:Anchor Classes="Muted">
<u:AnchorItem Header="尺寸" />
<u:AnchorItem Header="组件" />
<u:AnchorItem Header="设计语言" />
<u:AnchorItem Header="物料平台" />
<u:AnchorItem Header="主题商店" />
</u:Anchor>
<u:Anchor>
<u:AnchorItem Header="1. 动态展示">
<u:AnchorItem Header="1.1 组件">
<u:AnchorItem Header="1.1.1 Avatar" />
<u:AnchorItem Header="1.1.2 Button" />
<u:AnchorItem Header="1.1.3 Icon" />
</u:AnchorItem>
<u:AnchorItem Header="1.2 物料" />
<u:AnchorItem Header="1.3 主题商店" />
</u:AnchorItem>
<u:AnchorItem Header="2. 设计语言" />
</u:Anchor>
</StackPanel>
</TabItem>
</TabControl>
</UserControl>

View File

@@ -0,0 +1,13 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
namespace Ursa.Demo.Pages;
public partial class AnchorDemo : UserControl
{
public AnchorDemo()
{
InitializeComponent();
}
}

View File

@@ -0,0 +1,44 @@
using System.Collections.Generic;
using System.Collections.ObjectModel;
using CommunityToolkit.Mvvm.ComponentModel;
namespace Ursa.Demo.ViewModels;
public partial class AnchorDemoViewModel : ObservableObject
{
public List<AnchorItemViewModel> AnchorItems { get; } = new()
{
new AnchorItemViewModel { AnchorId = "anchor1", Header = "Anchor 1" },
new AnchorItemViewModel { AnchorId = "anchor2", Header = "Anchor 2" },
new AnchorItemViewModel
{
AnchorId = "anchor3", Header = "Anchor 3",
Children =
[
new AnchorItemViewModel() { AnchorId = "anchor3-1", Header = "Anchor 3.1" },
new AnchorItemViewModel()
{
AnchorId = "anchor3-2", Header = "Anchor 3.2",
Children =
[
new AnchorItemViewModel() { AnchorId = "anchor3-2-1", Header = "Anchor 3.2.1" },
new AnchorItemViewModel() { AnchorId = "anchor3-2-2", Header = "Anchor 3.2.2" },
new AnchorItemViewModel() { AnchorId = "anchor3-2-3", Header = "Anchor 3.2.3" }
]
},
new AnchorItemViewModel() { AnchorId = "anchor3-3", Header = "Anchor 3.3" }
]
},
new AnchorItemViewModel { AnchorId = "anchor4", Header = "Anchor 4" },
new AnchorItemViewModel { AnchorId = "anchor5", Header = "Anchor 5" },
new AnchorItemViewModel { AnchorId = "anchor6", Header = "Anchor 6" },
new AnchorItemViewModel { AnchorId = "anchor7", Header = "Anchor 7" },
};
}
public partial class AnchorItemViewModel : ObservableObject
{
[ObservableProperty] private string? _anchorId;
[ObservableProperty] private string? _header;
public ObservableCollection<AnchorItemViewModel>? Children { get; set; }
}

View File

@@ -86,8 +86,9 @@ public partial class MainViewViewModel : ViewModelBase
MenuKeys.MenuKeyToolBar => new ToolBarDemoViewModel(),
MenuKeys.MenuKeyTreeComboBox => new TreeComboBoxDemoViewModel(),
MenuKeys.MenuKeyTwoTonePathIcon => new TwoTonePathIconDemoViewModel(),
MenuKeys.AspectRatioLayout => new AspectRatioLayoutDemoViewModel(),
MenuKeys.PathPicker => new PathPickerDemoViewModel(),
MenuKeys.MenuKeyAspectRatioLayout => new AspectRatioLayoutDemoViewModel(),
MenuKeys.MenuKeyPathPicker => new PathPickerDemoViewModel(),
MenuKeys.MenuKeyAnchor => new AnchorDemoViewModel(),
_ => throw new ArgumentOutOfRangeException(nameof(s), s, null)
};
}

View File

@@ -26,7 +26,7 @@ public class MenuViewModel : ViewModelBase
new() { MenuHeader = "MultiComboBox", Key = MenuKeys.MenuKeyMultiComboBox },
new() { MenuHeader = "Numeric UpDown", Key = MenuKeys.MenuKeyNumericUpDown },
new() { MenuHeader = "NumPad", Key = MenuKeys.MenuKeyNumPad },
new() { MenuHeader = "PathPicker", Key = MenuKeys.PathPicker, Status = "New" },
new() { MenuHeader = "PathPicker", Key = MenuKeys.MenuKeyPathPicker, Status = "New" },
new() { MenuHeader = "PinCode", Key = MenuKeys.MenuKeyPinCode },
new() { MenuHeader = "RangeSlider", Key = MenuKeys.MenuKeyRangeSlider },
new() { MenuHeader = "Rating", Key = MenuKeys.MenuKeyRating },
@@ -67,6 +67,7 @@ public class MenuViewModel : ViewModelBase
{
MenuHeader = "Navigation & Menus", Children = new ObservableCollection<MenuItemViewModel>
{
new() { MenuHeader = "Anchor", Key = MenuKeys.MenuKeyAnchor, Status = "New" },
new() { MenuHeader = "Breadcrumb", Key = MenuKeys.MenuKeyBreadcrumb, Status = "Updated" },
new() { MenuHeader = "Nav Menu", Key = MenuKeys.MenuKeyNavMenu, Status = "Updated" },
new() { MenuHeader = "Pagination", Key = MenuKeys.MenuKeyPagination },
@@ -78,7 +79,7 @@ public class MenuViewModel : ViewModelBase
MenuHeader = "Layout & Display",
Children = new ObservableCollection<MenuItemViewModel>
{
new() { MenuHeader = "AspectRatioLayout", Key = MenuKeys.AspectRatioLayout },
new() { MenuHeader = "AspectRatioLayout", Key = MenuKeys.MenuKeyAspectRatioLayout },
new() { MenuHeader = "Avatar", Key = MenuKeys.MenuKeyAvatar, Status = "WIP" },
new() { MenuHeader = "Badge", Key = MenuKeys.MenuKeyBadge },
new() { MenuHeader = "Banner", Key = MenuKeys.MenuKeyBanner, Status = "Updated" },
@@ -154,6 +155,7 @@ public static class MenuKeys
public const string MenuKeyToolBar = "ToolBar";
public const string MenuKeyTreeComboBox = "TreeComboBox";
public const string MenuKeyTwoTonePathIcon = "TwoTonePathIcon";
public const string AspectRatioLayout = "AspectRatioLayout";
public const string PathPicker = "PathPicker";
public const string MenuKeyAspectRatioLayout = "AspectRatioLayout";
public const string MenuKeyPathPicker = "PathPicker";
public const string MenuKeyAnchor = "Anchor";
}