Merge pull request #28 from irihitech/menu

Menu
This commit is contained in:
Dong Bin
2023-06-30 23:58:43 +08:00
committed by GitHub
25 changed files with 359 additions and 180 deletions

View File

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

View File

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

View File

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

View File

@@ -9,7 +9,7 @@
d:DesignHeight="450"
d:DesignWidth="800"
x:CompileBindings="True"
x:DataType="vm:ButtonGroupViewModel"
x:DataType="vm:ButtonGroupDemoViewModel"
mc:Ignorable="d">
<StackPanel Margin="20" Spacing="20">

View File

@@ -10,6 +10,6 @@ public partial class ButtonGroupDemo : UserControl
public ButtonGroupDemo()
{
InitializeComponent();
this.DataContext = new ButtonGroupViewModel();
this.DataContext = new ButtonGroupDemoViewModel();
}
}

View File

@@ -42,7 +42,7 @@
<u:NavigationMenu.ItemTemplate>
<converters:MenuDataTemplateSelector>
<converters:MenuDataTemplateSelector.MenuTemplate>
<DataTemplate DataType="vm:NavigationMenuItemViewModel">
<DataTemplate DataType="vm:MenuItemViewModel">
<u:NavigationMenuItem Header="{Binding MenuHeader}" ItemsSource="{Binding Children}">
<u:NavigationMenuItem.Icon>
<PathIcon
@@ -54,7 +54,7 @@
</DataTemplate>
</converters:MenuDataTemplateSelector.MenuTemplate>
<converters:MenuDataTemplateSelector.SeparatorTemplate>
<DataTemplate DataType="vm:NavigationMenuItemViewModel">
<DataTemplate DataType="vm:MenuItemViewModel">
<u:NavigationMenuSeparator Header="{Binding MenuHeader}" />
</DataTemplate>
</converters:MenuDataTemplateSelector.SeparatorTemplate>

View File

@@ -9,7 +9,6 @@
</PropertyGroup>
<ItemGroup>
<Folder Include="Models\" />
<AvaloniaResource Include="Assets\**" />
<None Remove=".gitignore" />
</ItemGroup>

View File

@@ -0,0 +1,6 @@
namespace Ursa.Demo.ViewModels;
public class BadgeDemoViewModel: ViewModelBase
{
}

View File

@@ -0,0 +1,6 @@
namespace Ursa.Demo.ViewModels;
public class BannerDemoViewModel: ViewModelBase
{
}

View File

@@ -2,9 +2,9 @@ using System.Collections.ObjectModel;
namespace Ursa.Demo.ViewModels;
public class ButtonGroupViewModel: ViewModelBase
public class ButtonGroupDemoViewModel: ViewModelBase
{
public ObservableCollection<string> Items { get; set; } = new ObservableCollection<string>()
public ObservableCollection<string> Items { get; set; } = new ()
{
"Ding", "Otter", "Husky", "Mr. 17", "Cass"
};

View File

@@ -0,0 +1,6 @@
namespace Ursa.Demo.ViewModels;
public class DividerDemoViewModel: ViewModelBase
{
}

View File

@@ -0,0 +1,6 @@
namespace Ursa.Demo.ViewModels;
public class IPv4BoxDemoViewModel: ViewModelBase
{
}

View File

@@ -0,0 +1,6 @@
namespace Ursa.Demo.ViewModels;
public class LoadingDemoViewModel: ViewModelBase
{
}

View File

@@ -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<MainWindowViewModel, string>(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(),
};
}
}

View File

@@ -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<MenuItemViewModel> Children { get; set; } = new();
public ICommand ActivateCommand { get; set; }
public MenuItemViewModel()
{
ActivateCommand = new RelayCommand(OnActivate);
}
private void OnActivate()
{
if (IsSeparator) return;
WeakReferenceMessenger.Default.Send<string>(Key);
}
}

View File

@@ -0,0 +1,26 @@
using System.Collections.ObjectModel;
namespace Ursa.Demo.ViewModels;
public class MenuViewModel: ViewModelBase
{
public ObservableCollection<MenuItemViewModel> MenuItems { get; set; }
public MenuViewModel()
{
MenuItems = new ObservableCollection<MenuItemViewModel>()
{
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 },
};
}
}

View File

@@ -5,18 +5,18 @@ namespace Ursa.Demo.ViewModels;
public class NavigationMenuDemoViewModel: ObservableObject
{
public ObservableCollection<NavigationMenuItemViewModel> MenuItems { get; set; } = new()
public ObservableCollection<MenuItemViewModel> MenuItems { get; set; } = new()
{
new NavigationMenuItemViewModel()
new MenuItemViewModel()
{
MenuHeader = "任务管理",
MenuIconName = "User",
Children = new ObservableCollection<NavigationMenuItemViewModel>()
Children = new ObservableCollection<MenuItemViewModel>()
{
new (){
MenuHeader = "公告管理" ,
MenuIconName = "Star",
Children = new ObservableCollection<NavigationMenuItemViewModel>()
Children = new ObservableCollection<MenuItemViewModel>()
{
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<NavigationMenuItemViewModel>()
Children = new ObservableCollection<MenuItemViewModel>()
{
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<NavigationMenuItemViewModel> Children { get; set; } = new();
}

View File

@@ -5,7 +5,7 @@ using CommunityToolkit.Mvvm.ComponentModel;
namespace Ursa.Demo.ViewModels;
public class PaginationDemoViewModel: ObservableObject
public class PaginationDemoViewModel: ViewModelBase
{
public AvaloniaList<int> PageSizes { get; set; } = new() { 10, 20, 50, 100 };
}

View File

@@ -0,0 +1,6 @@
namespace Ursa.Demo.ViewModels;
public class TagInputDemoViewModel: ViewModelBase
{
}

View File

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

View File

@@ -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 @@
<vm:MainWindowViewModel />
</Design.DataContext>
<Grid RowDefinitions="Auto, *">
<Grid ColumnDefinitions="Auto, *" RowDefinitions="Auto, *">
<Border
Grid.RowSpan="2"
Padding="8,4"
VerticalAlignment="Stretch"
Theme="{DynamicResource CardBorder}">
<u:NavigationMenu ItemsSource="{Binding Menus.MenuItems}" ShowCollapseButton="True">
<u:NavigationMenu.Header>
<TextBlock
Classes="H4"
Text="Ursa"
Theme="{DynamicResource TitleTextBlock}" />
</u:NavigationMenu.Header>
<u:NavigationMenu.Icon>
<Image
Width="48"
Height="48"
RenderOptions.BitmapInterpolationMode="HighQuality"
Source="../Assets/Ursa.ico" />
</u:NavigationMenu.Icon>
<u:NavigationMenu.ItemTemplate>
<converters:MenuDataTemplateSelector>
<converters:MenuDataTemplateSelector.MenuTemplate>
<DataTemplate DataType="vm:MenuItemViewModel">
<u:NavigationMenuItem
Command="{Binding ActivateCommand}"
Header="{Binding MenuHeader}"
ItemsSource="{Binding Children}">
<u:NavigationMenuItem.Icon>
<Ellipse
Width="10"
Height="10"
Fill="LightGray" />
</u:NavigationMenuItem.Icon>
</u:NavigationMenuItem>
</DataTemplate>
</converters:MenuDataTemplateSelector.MenuTemplate>
<converters:MenuDataTemplateSelector.SeparatorTemplate>
<DataTemplate DataType="vm:MenuItemViewModel">
<u:NavigationMenuSeparator Header="{Binding MenuHeader}" />
</DataTemplate>
</converters:MenuDataTemplateSelector.SeparatorTemplate>
</converters:MenuDataTemplateSelector>
</u:NavigationMenu.ItemTemplate>
</u:NavigationMenu>
</Border>
<ToggleButton
Grid.Row="0"
Grid.Column="1"
HorizontalAlignment="Right"
Content="Update Theme"
IsCheckedChanged="ToggleButton_OnIsCheckedChanged" />
<TabControl Grid.Row="1" TabStripPlacement="Left">
<TabItem Header="Badge">
<pages:BadgeDemo />
</TabItem>
<TabItem Header="Banner">
<pages:BannerDemo />
</TabItem>
<TabItem Header="ButtonGroup">
<pages:ButtonGroupDemo />
</TabItem>
<TabItem Header="Divider">
<pages:DividerDemo />
</TabItem>
<TabItem Header="IPv4Box">
<pages:IPv4BoxDemo />
</TabItem>
<TabItem Header="Loading">
<pages:LoadingDemo />
</TabItem>
<TabItem Header="Navigation">
<pages:NavigationMenuDemo />
</TabItem>
<TabItem Header="Pagination">
<pages:PaginationDemo />
</TabItem>
<TabItem Header="TagInput">
<pages:TagInputDemo />
</TabItem>
<TabItem Header="Timeline">
<pages:TimelineDemo />
</TabItem>
</TabControl>
<ContentControl
Grid.Row="1"
Grid.Column="1"
Content="{Binding Content}">
<ContentControl.ContentTemplate>
<converters:ViewLocator />
</ContentControl.ContentTemplate>
</ContentControl>
</Grid>
</Window>

View File

@@ -24,57 +24,59 @@
<DoubleTransition Property="Width" Duration="0:0:0.1" />
</Transitions>
</Border.Transitions>
<Grid
Name="PART_RootGrid"
HorizontalAlignment="Stretch"
Background="{TemplateBinding Background}"
RowDefinitions="Auto, *, Auto, Auto">
<StackPanel
Margin="{DynamicResource NavigationMenuHeaderMargin}"
HorizontalAlignment="Center"
Orientation="Horizontal">
<ContentPresenter
Name="PART_IconPresenter"
Margin="{DynamicResource NavigationMenuIconMargin}"
VerticalAlignment="Center"
Content="{TemplateBinding Icon}" />
<ContentPresenter
Name="PART_HeaderPresenter"
VerticalAlignment="Center"
Content="{TemplateBinding Header}"
ContentTemplate="{TemplateBinding HeaderTemplate}" />
<ScrollViewer HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto">
<Grid
Name="PART_RootGrid"
HorizontalAlignment="Stretch"
Background="{TemplateBinding Background}"
RowDefinitions="Auto, *, Auto, Auto">
<StackPanel
Margin="{DynamicResource NavigationMenuHeaderMargin}"
HorizontalAlignment="Center"
Orientation="Horizontal">
<ContentPresenter
Name="PART_IconPresenter"
Margin="{DynamicResource NavigationMenuIconMargin}"
VerticalAlignment="Center"
Content="{TemplateBinding Icon}" />
<ContentPresenter
Name="PART_HeaderPresenter"
VerticalAlignment="Center"
Content="{TemplateBinding Header}"
ContentTemplate="{TemplateBinding HeaderTemplate}" />
</StackPanel>
<ItemsPresenter Grid.Row="1" ItemsPanel="{TemplateBinding ItemsPanel}" />
<ContentPresenter
Name="PART_FooterPresenter"
Grid.Row="2"
Content="{TemplateBinding Footer}"
ContentTemplate="{TemplateBinding FooterTemplate}" />
<ToggleSwitch
Name="{x:Static u:NavigationMenu.PART_CloseButton}"
Grid.Row="3"
Content="Open"
IsChecked="{TemplateBinding IsClosed,
Mode=TwoWay}"
IsVisible="{TemplateBinding ShowCollapseButton}"
Theme="{DynamicResource ButtonToggleSwitch}">
<ToggleSwitch.OnContent>
<PathIcon
Width="{DynamicResource NavigationMenuExpandIconWidth}"
Height="{DynamicResource NavigationMenuExpandIconHeight}"
Data="{DynamicResource NavigationMenuExpandIconGlyph}"
Foreground="{DynamicResource ButtonDefaultTertiaryForeground}" />
</ToggleSwitch.OnContent>
<ToggleSwitch.OffContent>
<PathIcon
Width="{DynamicResource NavigationMenuExpandIconWidth}"
Height="{DynamicResource NavigationMenuExpandIconHeight}"
Data="{DynamicResource NavigationMenuExpandIconGlyph}"
Foreground="{DynamicResource ButtonDefaultTertiaryForeground}" />
</ToggleSwitch.OffContent>
</ToggleSwitch>
</Grid>
</StackPanel>
<ItemsPresenter Grid.Row="1" ItemsPanel="{TemplateBinding ItemsPanel}" />
<ContentPresenter
Name="PART_FooterPresenter"
Grid.Row="2"
Content="{TemplateBinding Footer}"
ContentTemplate="{TemplateBinding FooterTemplate}" />
<ToggleSwitch
Name="{x:Static u:NavigationMenu.PART_CloseButton}"
Grid.Row="3"
Content="Open"
IsChecked="{TemplateBinding IsClosed,
Mode=TwoWay}"
IsVisible="{TemplateBinding ShowCollapseButton}"
Theme="{DynamicResource ButtonToggleSwitch}">
<ToggleSwitch.OnContent>
<PathIcon
Width="{DynamicResource NavigationMenuExpandIconWidth}"
Height="{DynamicResource NavigationMenuExpandIconHeight}"
Data="{DynamicResource NavigationMenuExpandIconGlyph}"
Foreground="{DynamicResource ButtonDefaultTertiaryForeground}" />
</ToggleSwitch.OnContent>
<ToggleSwitch.OffContent>
<PathIcon
Width="{DynamicResource NavigationMenuExpandIconWidth}"
Height="{DynamicResource NavigationMenuExpandIconHeight}"
Data="{DynamicResource NavigationMenuExpandIconGlyph}"
Foreground="{DynamicResource ButtonDefaultTertiaryForeground}" />
</ToggleSwitch.OffContent>
</ToggleSwitch>
</Grid>
</ScrollViewer>
</Border>
</ControlTemplate>
</Setter>

View File

@@ -1,5 +1,7 @@
<ResourceDictionary xmlns="https://github.com/avaloniaui" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sys="clr-namespace:System;assembly=netstandard">
<ResourceDictionary
xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sys="clr-namespace:System;assembly=netstandard">
<Geometry x:Key="NavigationMenuExpandIconGlyph">M5 2H19C20.6569 2 22 3.34315 22 5V19C22 20.6569 20.6569 22 19 22H5C3.34315 22 2 20.6569 2 19V5C2 3.34315 3.34315 2 5 2ZM6 4C5.44772 4 5 4.44772 5 5V19C5 19.5523 5.44772 20 6 20H9C9.55229 20 10 19.5523 10 19V5C10 4.44772 9.55229 4 9 4H6Z</Geometry>
<Geometry x:Key="NavigationMenuItemExpandIconGlyph">M4.08045 7.59809C4.66624 7.01231 5.61599 7.01231 6.20177 7.59809L11.8586 13.2549L17.5155 7.59809C18.1013 7.01231 19.051 7.01231 19.6368 7.59809C20.2226 8.18388 20.2226 9.13363 19.6368 9.71941L12.9193 16.4369C12.3335 17.0227 11.3838 17.0227 10.798 16.4369L4.08045 9.71941C3.49467 9.13363 3.49467 8.18388 4.08045 7.59809Z</Geometry>
@@ -11,7 +13,7 @@
<sys:Double x:Key="NavigationMenuItemIconMinWidth">24</sys:Double>
<sys:Double x:Key="NavigationMenuItemExpandIconWidth">8</sys:Double>
<sys:Double x:Key="NavigationMenuItemExpandIconHeight">8</sys:Double>
<sys:Double x:Key="NavigationMenuItemIconMargin">0</sys:Double>
<Thickness x:Key="NavigationMenuItemIconMargin">0</Thickness>
<sys:Double x:Key="NavigationMenuItemCollapsedHeight">0</sys:Double>
<sys:Double x:Key="NavigationMenuItemCollapsedOpacity">0</sys:Double>
@@ -25,7 +27,7 @@
<Thickness x:Key="NavigationMenuItemDefaultMargin">0,2</Thickness>
<Thickness x:Key="NavigationMenuItemDefaultPadding">8</Thickness>
<Thickness x:Key="NavigationMenuItemDefaultCornerRadius">6</Thickness>
<CornerRadius x:Key="NavigationMenuItemDefaultCornerRadius">6</CornerRadius>
<Thickness x:Key="NavigationMenuItemHeaderMargin">12,0</Thickness>
<Thickness x:Key="NavigationMenuItemExpandIconMargin">12,0</Thickness>
<Thickness x:Key="NavigationMenuItemFlyoutMargin">8</Thickness>

View File

@@ -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<Popup>(PART_Popup);
Level = CalculateDistanceFromLogicalParent<NavigationMenu>(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;
}

View File

@@ -1,5 +1,6 @@
using System.Collections;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using Avalonia;
using Avalonia.Collections;
using Avalonia.Controls;
@@ -128,7 +129,7 @@ public class TagInput : TemplatedControl
private void OnInputThemePropertyChanged(AvaloniaPropertyChangedEventArgs args)
{
var newTheme = args.GetNewValue<ControlTheme>();
if (newTheme.TargetType == typeof(TextBox))
if (newTheme?.TargetType == typeof(TextBox))
{
_textBox.Theme = newTheme;
}
@@ -137,6 +138,7 @@ public class TagInput : TemplatedControl
private void OnTagsPropertyChanged(AvaloniaPropertyChangedEventArgs args)
{
var newTags = args.GetNewValue<IList<string>>();
var oldTags = args.GetOldValue<IList<string>>();
for (int i = 0; i < Items.Count - 1; i++)
{
Items.RemoveAt(Items.Count - 1);
@@ -146,6 +148,46 @@ public class TagInput : TemplatedControl
{
Items.Insert(Items.Count - 1, newTags[i]);
}
if (oldTags is INotifyCollectionChanged inccold)
{
inccold.CollectionChanged-= OnCollectionChanged;
}
if (Tags is INotifyCollectionChanged incc)
{
incc.CollectionChanged += OnCollectionChanged;
}
}
private void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if (e.Action == NotifyCollectionChangedAction.Add)
{
var items = e.NewItems;
int index = e.NewStartingIndex;
foreach (var item in items)
{
if (item is string s)
{
Items.Insert(index, s);
index++;
}
}
}
else if (e.Action == NotifyCollectionChangedAction.Remove)
{
var items = e.OldItems;
int index = e.OldStartingIndex;
foreach (var item in items)
{
if (item is string s)
{
Items.RemoveAt(index);
}
}
}
}
private void OnTextBoxKeyDown(object? sender, KeyEventArgs args)
@@ -173,7 +215,7 @@ public class TagInput : TemplatedControl
for (int i = 0; i < values.Length; i++)
{
int index = Items.Count - 1;
Items.Insert(index, values[i]);
// Items.Insert(index, values[i]);
Tags.Insert(index, values[i]);
}
@@ -189,7 +231,7 @@ public class TagInput : TemplatedControl
return;
}
int index = Items.Count - 2;
Items.RemoveAt(index);
// Items.RemoveAt(index);
Tags.RemoveAt(index);
}
}
@@ -204,7 +246,7 @@ public class TagInput : TemplatedControl
int? index = _itemsControl?.IndexFromContainer(presenter);
if (index is >= 0 && index < Items.Count - 1)
{
Items.RemoveAt(index.Value);
// Items.RemoveAt(index.Value);
Tags.RemoveAt(index.Value);
}
}