diff --git a/demo/Ursa.Demo/Converters/MenuDataTemplateSelector.cs b/demo/Ursa.Demo/Converters/MenuDataTemplateSelector.cs index a91b109..03d73d1 100644 --- a/demo/Ursa.Demo/Converters/MenuDataTemplateSelector.cs +++ b/demo/Ursa.Demo/Converters/MenuDataTemplateSelector.cs @@ -11,12 +11,11 @@ public class MenuDataTemplateSelector: IDataTemplate public Control? Build(object? param) { - if (param is NavigationMenuItemViewModel vm) + if (param is MenuItemViewModel vm) { if (vm.IsSeparator) return SeparatorTemplate?.Build(vm); else return MenuTemplate?.Build(vm); } - return null; } diff --git a/demo/Ursa.Demo/Converters/ViewLocator.cs b/demo/Ursa.Demo/Converters/ViewLocator.cs new file mode 100644 index 0000000..fbbbece --- /dev/null +++ b/demo/Ursa.Demo/Converters/ViewLocator.cs @@ -0,0 +1,29 @@ +using System; +using Avalonia.Controls; +using Avalonia.Controls.Templates; +using Ursa.Demo.Pages; + +namespace Ursa.Demo.Converters; + +public class ViewLocator: IDataTemplate +{ + public Control? Build(object? param) + { + if (param is null) return null; + var name = param.GetType().Name!.Replace("ViewModel", ""); + var type = Type.GetType("Ursa.Demo.Pages."+name); + if (type != null) + { + return (Control)Activator.CreateInstance(type)!; + } + else + { + return new TextBlock { Text = "Not Found: " + name }; + } + } + + public bool Match(object? data) + { + return true; + } +} \ No newline at end of file diff --git a/demo/Ursa.Demo/Models/MenuKeys.cs b/demo/Ursa.Demo/Models/MenuKeys.cs new file mode 100644 index 0000000..5a76eb9 --- /dev/null +++ b/demo/Ursa.Demo/Models/MenuKeys.cs @@ -0,0 +1,15 @@ +namespace Ursa.Demo; + +public static class MenuKeys +{ + public const string MenuKeyBadge = "Badge"; + public const string MenuKeyBanner = "Banner"; + public const string MenuKeyButtonGroup = "ButtonGroup"; + public const string MenuKeyDivider = "Divider"; + public const string MenuKeyIpBox = "IPv4Box"; + public const string MenuKeyLoading = "Loading"; + public const string MenuKeyNavigation = "Navigation"; + public const string MenuKeyPagination = "Pagination"; + public const string MenuKeyTagInput = "TagInput"; + public const string MenuKeyTimeline = "Timeline"; +} \ No newline at end of file diff --git a/demo/Ursa.Demo/Pages/ButtonGroupDemo.axaml b/demo/Ursa.Demo/Pages/ButtonGroupDemo.axaml index 510c423..30c0a03 100644 --- a/demo/Ursa.Demo/Pages/ButtonGroupDemo.axaml +++ b/demo/Ursa.Demo/Pages/ButtonGroupDemo.axaml @@ -9,7 +9,7 @@ d:DesignHeight="450" d:DesignWidth="800" x:CompileBindings="True" - x:DataType="vm:ButtonGroupViewModel" + x:DataType="vm:ButtonGroupDemoViewModel" mc:Ignorable="d"> diff --git a/demo/Ursa.Demo/Pages/ButtonGroupDemo.axaml.cs b/demo/Ursa.Demo/Pages/ButtonGroupDemo.axaml.cs index 695bcd1..533130a 100644 --- a/demo/Ursa.Demo/Pages/ButtonGroupDemo.axaml.cs +++ b/demo/Ursa.Demo/Pages/ButtonGroupDemo.axaml.cs @@ -10,6 +10,6 @@ public partial class ButtonGroupDemo : UserControl public ButtonGroupDemo() { InitializeComponent(); - this.DataContext = new ButtonGroupViewModel(); + this.DataContext = new ButtonGroupDemoViewModel(); } } \ No newline at end of file diff --git a/demo/Ursa.Demo/Pages/NavigationMenuDemo.axaml b/demo/Ursa.Demo/Pages/NavigationMenuDemo.axaml index 8e608a7..651c3e8 100644 --- a/demo/Ursa.Demo/Pages/NavigationMenuDemo.axaml +++ b/demo/Ursa.Demo/Pages/NavigationMenuDemo.axaml @@ -42,7 +42,7 @@ - + - + diff --git a/demo/Ursa.Demo/Ursa.Demo.csproj b/demo/Ursa.Demo/Ursa.Demo.csproj index 328116c..f11d2df 100644 --- a/demo/Ursa.Demo/Ursa.Demo.csproj +++ b/demo/Ursa.Demo/Ursa.Demo.csproj @@ -9,7 +9,6 @@ - diff --git a/demo/Ursa.Demo/ViewModels/BadgeDemoViewModel.cs b/demo/Ursa.Demo/ViewModels/BadgeDemoViewModel.cs new file mode 100644 index 0000000..afd9963 --- /dev/null +++ b/demo/Ursa.Demo/ViewModels/BadgeDemoViewModel.cs @@ -0,0 +1,6 @@ +namespace Ursa.Demo.ViewModels; + +public class BadgeDemoViewModel: ViewModelBase +{ + +} \ No newline at end of file diff --git a/demo/Ursa.Demo/ViewModels/BannerDemoViewModel.cs b/demo/Ursa.Demo/ViewModels/BannerDemoViewModel.cs new file mode 100644 index 0000000..34a0ded --- /dev/null +++ b/demo/Ursa.Demo/ViewModels/BannerDemoViewModel.cs @@ -0,0 +1,6 @@ +namespace Ursa.Demo.ViewModels; + +public class BannerDemoViewModel: ViewModelBase +{ + +} \ No newline at end of file diff --git a/demo/Ursa.Demo/ViewModels/ButtonGroupViewModel.cs b/demo/Ursa.Demo/ViewModels/ButtonGroupDemoViewModel.cs similarity index 71% rename from demo/Ursa.Demo/ViewModels/ButtonGroupViewModel.cs rename to demo/Ursa.Demo/ViewModels/ButtonGroupDemoViewModel.cs index aeb2400..88c5299 100644 --- a/demo/Ursa.Demo/ViewModels/ButtonGroupViewModel.cs +++ b/demo/Ursa.Demo/ViewModels/ButtonGroupDemoViewModel.cs @@ -2,9 +2,9 @@ using System.Collections.ObjectModel; namespace Ursa.Demo.ViewModels; -public class ButtonGroupViewModel: ViewModelBase +public class ButtonGroupDemoViewModel: ViewModelBase { - public ObservableCollection Items { get; set; } = new ObservableCollection() + public ObservableCollection Items { get; set; } = new () { "Ding", "Otter", "Husky", "Mr. 17", "Cass" }; diff --git a/demo/Ursa.Demo/ViewModels/DividerDemoViewModel.cs b/demo/Ursa.Demo/ViewModels/DividerDemoViewModel.cs new file mode 100644 index 0000000..a7b433c --- /dev/null +++ b/demo/Ursa.Demo/ViewModels/DividerDemoViewModel.cs @@ -0,0 +1,6 @@ +namespace Ursa.Demo.ViewModels; + +public class DividerDemoViewModel: ViewModelBase +{ + +} \ No newline at end of file diff --git a/demo/Ursa.Demo/ViewModels/IPv4BoxDemoViewModel.cs b/demo/Ursa.Demo/ViewModels/IPv4BoxDemoViewModel.cs new file mode 100644 index 0000000..ff17a77 --- /dev/null +++ b/demo/Ursa.Demo/ViewModels/IPv4BoxDemoViewModel.cs @@ -0,0 +1,6 @@ +namespace Ursa.Demo.ViewModels; + +public class IPv4BoxDemoViewModel: ViewModelBase +{ + +} \ No newline at end of file diff --git a/demo/Ursa.Demo/ViewModels/LoadingDemoViewModel.cs b/demo/Ursa.Demo/ViewModels/LoadingDemoViewModel.cs new file mode 100644 index 0000000..0239ec1 --- /dev/null +++ b/demo/Ursa.Demo/ViewModels/LoadingDemoViewModel.cs @@ -0,0 +1,6 @@ +namespace Ursa.Demo.ViewModels; + +public class LoadingDemoViewModel: ViewModelBase +{ + +} \ No newline at end of file diff --git a/demo/Ursa.Demo/ViewModels/MainWindowViewModel.cs b/demo/Ursa.Demo/ViewModels/MainWindowViewModel.cs index 9ac0155..7fdbd75 100644 --- a/demo/Ursa.Demo/ViewModels/MainWindowViewModel.cs +++ b/demo/Ursa.Demo/ViewModels/MainWindowViewModel.cs @@ -1,6 +1,40 @@ -namespace Ursa.Demo.ViewModels; + +using CommunityToolkit.Mvvm.Messaging; + +namespace Ursa.Demo.ViewModels; public class MainWindowViewModel : ViewModelBase { - public string Greeting => "Welcome to Avalonia!"; + public MenuViewModel Menus { get; set; } = new MenuViewModel(); + + private object? _content; + public object? Content + { + get => _content; + set => SetProperty(ref _content, value); + } + + public MainWindowViewModel() + { + WeakReferenceMessenger.Default.Register(this, OnNavigation); + } + + + + private void OnNavigation(MainWindowViewModel vm, string s) + { + Content = s switch + { + MenuKeys.MenuKeyBadge => new BadgeDemoViewModel(), + MenuKeys.MenuKeyBanner => new BannerDemoViewModel(), + MenuKeys.MenuKeyButtonGroup => new ButtonGroupDemoViewModel(), + MenuKeys.MenuKeyDivider => new DividerDemoViewModel(), + MenuKeys.MenuKeyIpBox => new IPv4BoxDemoViewModel(), + MenuKeys.MenuKeyLoading => new LoadingDemoViewModel(), + MenuKeys.MenuKeyNavigation => new NavigationMenuDemoViewModel(), + MenuKeys.MenuKeyPagination => new PaginationDemoViewModel(), + MenuKeys.MenuKeyTagInput => new TagInputDemoViewModel(), + MenuKeys.MenuKeyTimeline => new TimelineDemoViewModel(), + }; + } } \ No newline at end of file diff --git a/demo/Ursa.Demo/ViewModels/MenuItemViewModel.cs b/demo/Ursa.Demo/ViewModels/MenuItemViewModel.cs new file mode 100644 index 0000000..42be205 --- /dev/null +++ b/demo/Ursa.Demo/ViewModels/MenuItemViewModel.cs @@ -0,0 +1,29 @@ +using System.Collections.ObjectModel; +using System.Windows.Input; +using CommunityToolkit.Mvvm.Input; +using CommunityToolkit.Mvvm.Messaging; + +namespace Ursa.Demo.ViewModels; + +public class MenuItemViewModel: ViewModelBase +{ + public string MenuHeader { get; set; } + public string MenuIconName { get; set; } + public string Key { get; set; } + + public bool IsSeparator { get; set; } + public ObservableCollection Children { get; set; } = new(); + + public ICommand ActivateCommand { get; set; } + + public MenuItemViewModel() + { + ActivateCommand = new RelayCommand(OnActivate); + } + + private void OnActivate() + { + if (IsSeparator) return; + WeakReferenceMessenger.Default.Send(Key); + } +} \ No newline at end of file diff --git a/demo/Ursa.Demo/ViewModels/MenuViewModel.cs b/demo/Ursa.Demo/ViewModels/MenuViewModel.cs new file mode 100644 index 0000000..9351ad9 --- /dev/null +++ b/demo/Ursa.Demo/ViewModels/MenuViewModel.cs @@ -0,0 +1,26 @@ +using System.Collections.ObjectModel; + +namespace Ursa.Demo.ViewModels; + +public class MenuViewModel: ViewModelBase +{ + public ObservableCollection MenuItems { get; set; } + + public MenuViewModel() + { + MenuItems = new ObservableCollection() + { + new() { MenuHeader = "Controls", IsSeparator = true }, + new() { MenuHeader = "Badge", Key = MenuKeys.MenuKeyBadge }, + new() { MenuHeader = "Banner", Key = MenuKeys.MenuKeyBanner }, + new() { MenuHeader = "ButtonGroup", Key = MenuKeys.MenuKeyButtonGroup }, + new() { MenuHeader = "Divider", Key = MenuKeys.MenuKeyDivider }, + new() { MenuHeader = "IPv4Box", Key = MenuKeys.MenuKeyIpBox }, + new() { MenuHeader = "Loading", Key = MenuKeys.MenuKeyLoading }, + new() { MenuHeader = "Navigation", Key = MenuKeys.MenuKeyNavigation }, + new() { MenuHeader = "Pagination", Key = MenuKeys.MenuKeyPagination }, + new() { MenuHeader = "TagInput", Key = MenuKeys.MenuKeyTagInput }, + new() { MenuHeader = "Timeline", Key = MenuKeys.MenuKeyTimeline }, + }; + } +} \ No newline at end of file diff --git a/demo/Ursa.Demo/ViewModels/NavigationMenuDemoViewModel.cs b/demo/Ursa.Demo/ViewModels/NavigationMenuDemoViewModel.cs index 4b7c0c6..7633771 100644 --- a/demo/Ursa.Demo/ViewModels/NavigationMenuDemoViewModel.cs +++ b/demo/Ursa.Demo/ViewModels/NavigationMenuDemoViewModel.cs @@ -5,18 +5,18 @@ namespace Ursa.Demo.ViewModels; public class NavigationMenuDemoViewModel: ObservableObject { - public ObservableCollection MenuItems { get; set; } = new() + public ObservableCollection MenuItems { get; set; } = new() { - new NavigationMenuItemViewModel() + new MenuItemViewModel() { MenuHeader = "任务管理", MenuIconName = "User", - Children = new ObservableCollection() + Children = new ObservableCollection() { new (){ MenuHeader = "公告管理" , MenuIconName = "Star", - Children = new ObservableCollection() + Children = new ObservableCollection() { new () {MenuHeader = "公告设置"}, new () {MenuHeader = "公告处理"} @@ -24,16 +24,16 @@ public class NavigationMenuDemoViewModel: ObservableObject new (){MenuHeader = "任务查询"} } }, - new NavigationMenuItemViewModel() + new MenuItemViewModel() { MenuHeader = "附加功能", IsSeparator = true, }, - new NavigationMenuItemViewModel() + new MenuItemViewModel() { MenuHeader = "任务平台", MenuIconName = "Gear", - Children = new ObservableCollection() + Children = new ObservableCollection() { new (){MenuHeader = "任务管理"}, new (){MenuHeader = "用户任务查询"} @@ -42,11 +42,3 @@ public class NavigationMenuDemoViewModel: ObservableObject }; } -public class NavigationMenuItemViewModel: ObservableObject -{ - public string MenuHeader { get; set; } - public string MenuIconName { get; set; } - - public bool IsSeparator { get; set; } - public ObservableCollection Children { get; set; } = new(); -} \ No newline at end of file diff --git a/demo/Ursa.Demo/ViewModels/PaginationDemoViewModel.cs b/demo/Ursa.Demo/ViewModels/PaginationDemoViewModel.cs index bf69393..55bb942 100644 --- a/demo/Ursa.Demo/ViewModels/PaginationDemoViewModel.cs +++ b/demo/Ursa.Demo/ViewModels/PaginationDemoViewModel.cs @@ -5,7 +5,7 @@ using CommunityToolkit.Mvvm.ComponentModel; namespace Ursa.Demo.ViewModels; -public class PaginationDemoViewModel: ObservableObject +public class PaginationDemoViewModel: ViewModelBase { public AvaloniaList PageSizes { get; set; } = new() { 10, 20, 50, 100 }; } \ No newline at end of file diff --git a/demo/Ursa.Demo/ViewModels/TagInputDemoViewModel.cs b/demo/Ursa.Demo/ViewModels/TagInputDemoViewModel.cs new file mode 100644 index 0000000..dfcdb38 --- /dev/null +++ b/demo/Ursa.Demo/ViewModels/TagInputDemoViewModel.cs @@ -0,0 +1,6 @@ +namespace Ursa.Demo.ViewModels; + +public class TagInputDemoViewModel: ViewModelBase +{ + +} \ No newline at end of file diff --git a/demo/Ursa.Demo/ViewModels/TimelineDemoViewModel.cs b/demo/Ursa.Demo/ViewModels/TimelineDemoViewModel.cs index 2420ee3..fc9e819 100644 --- a/demo/Ursa.Demo/ViewModels/TimelineDemoViewModel.cs +++ b/demo/Ursa.Demo/ViewModels/TimelineDemoViewModel.cs @@ -4,7 +4,7 @@ using Ursa.Controls; namespace Ursa.Demo.ViewModels; -public class TimelineDemoViewModel: ObservableObject +public class TimelineDemoViewModel: ViewModelBase { public TimelineItemViewModel[] Items { get; } = { @@ -46,62 +46,6 @@ public class TimelineDemoViewModel: ObservableObject Description = "Item 5", Content = "Content 5" }, - new() - { - Time = DateTime.Now, - TimeFormat = "HH:mm:ss", - Description = "Item 6", - Content = "Content 6" - }, - new() - { - Time = DateTime.Now, - TimeFormat = "HH:mm:ss", - Description = "Item 7", - Content = "Content 71231" - }, - new() - { - Time = DateTime.Now, - TimeFormat = "HH:mm:ss", - Description = "Item 8", - Content = "Content 8123123" - }, - new() - { - Time = DateTime.Now, - TimeFormat = "HH:mm:ss", - Description = "Item 9", - Content = "Content 9123123" - }, - new() - { - Time = DateTime.Now, - TimeFormat = "HH:mm:ss", - Description = "Item 10", - Content = "Content 1231231231231231231230" - }, - new() - { - Time = DateTime.Now, - TimeFormat = "HH:mm:ss", - Description = "Item 11", - Content = "Content 11231231" - }, - new() - { - Time = DateTime.Now, - TimeFormat = "HH:mm:ss", - Description = "Item 12", - Content = "Content 12123123123123" - }, - new() - { - Time = DateTime.Now, - TimeFormat = "HH:mm:ss", - Description = "Item 13", - Content = "Last" - } }; } diff --git a/demo/Ursa.Demo/Views/MainWindow.axaml b/demo/Ursa.Demo/Views/MainWindow.axaml index 9eb159c..f5cc372 100644 --- a/demo/Ursa.Demo/Views/MainWindow.axaml +++ b/demo/Ursa.Demo/Views/MainWindow.axaml @@ -2,13 +2,17 @@ x:Class="Ursa.Demo.Views.MainWindow" xmlns="https://github.com/avaloniaui" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + xmlns:converters="clr-namespace:Ursa.Demo.Converters" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:pages="clr-namespace:Ursa.Demo.Pages" + xmlns:u="https://irihi.tech/ursa" xmlns:vm="using:Ursa.Demo.ViewModels" Title="Ursa.Demo" d:DesignHeight="450" d:DesignWidth="800" + x:CompileBindings="True" + x:DataType="vm:MainWindowViewModel" Icon="/Assets/Ursa.ico" mc:Ignorable="d"> @@ -16,44 +20,67 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + diff --git a/src/Ursa.Themes.Semi/Controls/Navigation.axaml b/src/Ursa.Themes.Semi/Controls/Navigation.axaml index cb5e55c..c635374 100644 --- a/src/Ursa.Themes.Semi/Controls/Navigation.axaml +++ b/src/Ursa.Themes.Semi/Controls/Navigation.axaml @@ -24,57 +24,59 @@ - - - - + + + + + - - - - - - - - - - - - + + + + + + + + + + + + + diff --git a/src/Ursa/Controls/Navigation/NavigationMenuItem.cs b/src/Ursa/Controls/Navigation/NavigationMenuItem.cs index 946af82..d5ce45e 100644 --- a/src/Ursa/Controls/Navigation/NavigationMenuItem.cs +++ b/src/Ursa/Controls/Navigation/NavigationMenuItem.cs @@ -131,7 +131,7 @@ public class NavigationMenuItem: HeaderedSelectingItemsControl if (_rootMenu is not null) { - IsClosed = _rootMenu.IsClosed; + // IsClosed = _rootMenu.IsClosed; } _rootMenu?.GetObservable(NavigationMenu.IsClosedProperty) @@ -139,7 +139,7 @@ public class NavigationMenuItem: HeaderedSelectingItemsControl _rootMenu?.UpdateSelectionFromSelectedItem(_rootMenu.SelectedItem); _popup = e.NameScope.Find(PART_Popup); Level = CalculateDistanceFromLogicalParent(this) - 1; - bool isTopLevel = Level == 1; + bool isTopLevel = Level == 0; IsTopLevelMenuItem = isTopLevel; PseudoClasses.Set(PC_TopLevel, isTopLevel); } @@ -165,7 +165,7 @@ public class NavigationMenuItem: HeaderedSelectingItemsControl { if (_rootMenu is not null ) { - object? o = this.DataContext ?? this; + object? o = this.DataContext == _rootMenu.DataContext ? this : this.DataContext ?? this; _rootMenu.SelectedItem = o; } SetSelection(this, true, true); @@ -219,7 +219,7 @@ public class NavigationMenuItem: HeaderedSelectingItemsControl } else { - if (selected) + if (selected && source!=null) { _rootMenu?.UpdateSelection(this); } @@ -262,7 +262,10 @@ public class NavigationMenuItem: HeaderedSelectingItemsControl while (logical != null && !(logical is T)) { - ++result; + if (logical is NavigationMenuItem) + { + result++; + } logical = logical.LogicalParent; } diff --git a/src/Ursa/Controls/TagInput/TagInput.cs b/src/Ursa/Controls/TagInput/TagInput.cs index 5ee089b..77961c9 100644 --- a/src/Ursa/Controls/TagInput/TagInput.cs +++ b/src/Ursa/Controls/TagInput/TagInput.cs @@ -128,7 +128,7 @@ public class TagInput : TemplatedControl private void OnInputThemePropertyChanged(AvaloniaPropertyChangedEventArgs args) { var newTheme = args.GetNewValue(); - if (newTheme.TargetType == typeof(TextBox)) + if (newTheme?.TargetType == typeof(TextBox)) { _textBox.Theme = newTheme; }