diff --git a/Toolkit.Avalonia/Toolkit.Avalonia.csproj b/Toolkit.Avalonia/Toolkit.Avalonia.csproj index 2670c0f..a972a43 100644 --- a/Toolkit.Avalonia/Toolkit.Avalonia.csproj +++ b/Toolkit.Avalonia/Toolkit.Avalonia.csproj @@ -5,7 +5,7 @@ enable - + diff --git a/Toolkit.Foundation/Enumerate.cs b/Toolkit.Foundation/Enumerate.cs index 1f46636..8c54650 100644 --- a/Toolkit.Foundation/Enumerate.cs +++ b/Toolkit.Foundation/Enumerate.cs @@ -1,23 +1,23 @@ namespace Toolkit.Foundation; -public record Enumerate : IEnumerate +public record Enumerate : + IEnumerate { public object? Key { get; init; } + public EnumerateMode Mode { get; init; } + public static Enumerate With(TOptions options) where TOptions : class { return new Enumerate(options); } } -public interface IEnumerate -{ - object? Key { get; init; } -} - - -public record Enumerate(TOptions? Options = null) : IEnumerate +public record Enumerate(TOptions? Options = null) : + IEnumerate where TOptions : class { public object? Key { get; init; } + + public EnumerateMode Mode { get; init; } } \ No newline at end of file diff --git a/Toolkit.Foundation/EnumerateMode.cs b/Toolkit.Foundation/EnumerateMode.cs new file mode 100644 index 0000000..1827b0a --- /dev/null +++ b/Toolkit.Foundation/EnumerateMode.cs @@ -0,0 +1,7 @@ +namespace Toolkit.Foundation; + +public enum EnumerateMode +{ + Append, + Reset +} diff --git a/Toolkit.Foundation/IEnumerate.cs b/Toolkit.Foundation/IEnumerate.cs new file mode 100644 index 0000000..88782ca --- /dev/null +++ b/Toolkit.Foundation/IEnumerate.cs @@ -0,0 +1,8 @@ +namespace Toolkit.Foundation; + +public interface IEnumerate +{ + object? Key { get; init; } + + EnumerateMode Mode { get; init; } +} diff --git a/Toolkit.Foundation/NotificationAttribute.cs b/Toolkit.Foundation/NotificationAttribute.cs index d178ddd..cf48a5f 100644 --- a/Toolkit.Foundation/NotificationAttribute.cs +++ b/Toolkit.Foundation/NotificationAttribute.cs @@ -1,7 +1,13 @@ namespace Toolkit.Foundation; -[AttributeUsage(AttributeTargets.Class, Inherited = false)] +[AttributeUsage(AttributeTargets.Class, Inherited = true)] public class NotificationAttribute(object key) : Attribute { public object Key => key; +} + +public class EnumerateAttribute(object key, + EnumerateMode mode = EnumerateMode.Reset) : NotificationAttribute(key) +{ + public EnumerateMode Mode => mode; } \ No newline at end of file diff --git a/Toolkit.Foundation/ObservableCollectionViewModel.cs b/Toolkit.Foundation/ObservableCollectionViewModel.cs index 286da70..ff1748d 100644 --- a/Toolkit.Foundation/ObservableCollectionViewModel.cs +++ b/Toolkit.Foundation/ObservableCollectionViewModel.cs @@ -310,17 +310,19 @@ public partial class ObservableCollectionViewModel : public async Task Enumerate() { - Clear(); + if (this.GetAttribute() is EnumerateAttribute attribute) + { + if (attribute.Mode == EnumerateMode.Reset) + { + Clear(); + } - object? key = this.GetAttribute() - is NotificationAttribute attribute - ? this.GetPropertyValue(() => attribute.Key) is { } value ? value : attribute.Key - : null; - - await Publisher.PublishUI(CreateEnumeration(key)); + object? key = this.GetPropertyValue(() => attribute.Key) is { } value ? value : attribute.Key; + await Publisher.PublishUI(PrepareEnumeration(key)); + } } - protected virtual IEnumerate CreateEnumeration(object? key) => + protected virtual IEnumerate PrepareEnumeration(object? key) => new Enumerate() with { Key = key }; public void Insert(int index, TViewModel item) => diff --git a/Toolkit.Foundation/ObservableViewModel.cs b/Toolkit.Foundation/ObservableViewModel.cs index 60b3585..47a45b0 100644 --- a/Toolkit.Foundation/ObservableViewModel.cs +++ b/Toolkit.Foundation/ObservableViewModel.cs @@ -73,4 +73,16 @@ public partial class ObservableViewModel : IsInitialized = true; return Task.CompletedTask; } +} + +public partial class ObservableViewModel(IServiceProvider provider, + IServiceFactory factory, + IMediator mediator, + IPublisher publisher, + ISubscriber subscriber, + IDisposer disposer) : ObservableViewModel(provider, factory, mediator, publisher, subscriber, disposer) + where TValue : notnull +{ + [ObservableProperty] + private TValue? value; } \ No newline at end of file diff --git a/Toolkit.Foundation/SubscriptionManager.cs b/Toolkit.Foundation/SubscriptionManager.cs index a8aea60..2310df9 100644 --- a/Toolkit.Foundation/SubscriptionManager.cs +++ b/Toolkit.Foundation/SubscriptionManager.cs @@ -54,7 +54,17 @@ public class SubscriptionManager(SubscriptionCollection subscriptions) : { if (interfaceType.GetGenericArguments().FirstOrDefault() is Type argumentType) { - subscriptions.AddOrUpdate($"{(key is not null ? $"{key}:" : "")}{argumentType}", _ => new List { new(subscriber) }, (_, collection) => + if (key is not null) + { + subscriptions.AddOrUpdate($"{key}:{argumentType}", _ => new List { new(subscriber) }, (_, collection) => + { + collection.Add(new WeakReference(subscriber)); + return collection; + }); + + } + + subscriptions.AddOrUpdate($"{argumentType}", _ => new List { new(subscriber) }, (_, collection) => { collection.Add(new WeakReference(subscriber)); return collection; diff --git a/Toolkit.UI.Avalonia/NavigationViewItemExtension.cs b/Toolkit.UI.Avalonia/NavigationViewItemExtension.cs index 125b4f6..140a041 100644 --- a/Toolkit.UI.Avalonia/NavigationViewItemExtension.cs +++ b/Toolkit.UI.Avalonia/NavigationViewItemExtension.cs @@ -1,10 +1,86 @@ using Avalonia; +using Avalonia.Controls; using Avalonia.Interactivity; using Avalonia.LogicalTree; using Toolkit.UI.Controls.Avalonia; namespace Toolkit.UI.Avalonia; +public class ListBoxItemExtension +{ + public static readonly AttachedProperty IsItemClickEnabledProperty = + AvaloniaProperty.RegisterAttached("IsItemClickEnabled", + typeof(ListBoxItemExtension), false); + + public static readonly RoutedEvent ItemClickEvent = + RoutedEvent.Register("ItemClick", + RoutingStrategies.Bubble, typeof(ListBoxItemExtension)); + + static ListBoxItemExtension() + { + IsItemClickEnabledProperty.Changed.AddClassHandler(OnIsItemClickEnabledPropertyChanged); + } + + private static void OnIsItemClickEnabledPropertyChanged(ListBoxItem sender, + AvaloniaPropertyChangedEventArgs args) + { + bool TrySetupListBox() + { + if (sender.GetLogicalAncestors().OfType().FirstOrDefault() is ListBox listBox) + { + void OnItemInvoked(object? _, FluentAvalonia.UI.Controls.NavigationViewItemInvokedEventArgs args) + { + if (args.InvokedItemContainer == sender) + { + sender.RaiseEvent(new ItemInvokedEventArgs { RoutedEvent = ItemClickEvent }); + } + } + + void OnSelectionChanged(object? sender, SelectionChangedEventArgs args) + { + foreach (object item in args.AddedItems) + { + if (listBox.ContainerFromItem(item) == sender) + { + + } + } + } + + + listBox.SelectionChanged += OnSelectionChanged; + return true; + } + + return false; + } + + if (!TrySetupListBox()) + { + void OnAttachedToVisualTree(object? _, VisualTreeAttachmentEventArgs __) + { + sender.AttachedToVisualTree -= OnAttachedToVisualTree; + TrySetupListBox(); + } + + sender.AttachedToVisualTree += OnAttachedToVisualTree; + } + } + + public static bool GetIsItemClickEnabled(ListBoxItem element) => + element.GetValue(IsItemClickEnabledProperty); + + public static void SetIsItemClickEnabled(ListBoxItem element, bool value) => + element.SetValue(IsItemClickEnabledProperty, value); + + public static void AddItemClickHandler(ListBoxItem element, EventHandler handler) => + element.AddHandler(ItemClickEvent, handler); + + public static void RemoveItemClickHandler(ListBoxItem element, EventHandler handler) => + element.RemoveHandler(ItemClickEvent, handler); +} + + public class NavigationViewItemExtension { public static readonly AttachedProperty IsItemClickEnabledProperty = diff --git a/Toolkit.UI.Avalonia/Toolkit.UI.Avalonia.csproj b/Toolkit.UI.Avalonia/Toolkit.UI.Avalonia.csproj index 53a1c8c..3519c81 100644 --- a/Toolkit.UI.Avalonia/Toolkit.UI.Avalonia.csproj +++ b/Toolkit.UI.Avalonia/Toolkit.UI.Avalonia.csproj @@ -5,8 +5,8 @@ enable - - + + diff --git a/Toolkit.UI.Controls.Avalonia/Themes/ThemeResources.axaml b/Toolkit.UI.Controls.Avalonia/Themes/ThemeResources.axaml index 4d4bdf6..d8cdb09 100644 --- a/Toolkit.UI.Controls.Avalonia/Themes/ThemeResources.axaml +++ b/Toolkit.UI.Controls.Avalonia/Themes/ThemeResources.axaml @@ -4,7 +4,6 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:fluent="using:FluentAvalonia.Styling" xmlns:labs="using:Avalonia.Labs.Controls"> - diff --git a/Toolkit.UI.Controls.Avalonia/Themes/ThemeResources.axaml.cs b/Toolkit.UI.Controls.Avalonia/Themes/ThemeResources.axaml.cs index 2df8fe9..632cee3 100644 --- a/Toolkit.UI.Controls.Avalonia/Themes/ThemeResources.axaml.cs +++ b/Toolkit.UI.Controls.Avalonia/Themes/ThemeResources.axaml.cs @@ -1,10 +1,9 @@ using Avalonia.Markup.Xaml; -using Avalonia.Styling; +using FluentAvalonia.Styling; namespace Toolkit.UI.Controls.Avalonia; -public class ThemeResources : - Styles +public class ThemeResources : FluentAvaloniaTheme { public ThemeResources(IServiceProvider? provider = null) { diff --git a/Toolkit.UI.Controls.Avalonia/Toolkit.UI.Controls.Avalonia.csproj b/Toolkit.UI.Controls.Avalonia/Toolkit.UI.Controls.Avalonia.csproj index 4671d61..b0fb715 100644 --- a/Toolkit.UI.Controls.Avalonia/Toolkit.UI.Controls.Avalonia.csproj +++ b/Toolkit.UI.Controls.Avalonia/Toolkit.UI.Controls.Avalonia.csproj @@ -6,7 +6,7 @@ true - +