From e20890362ef038368f3b204eb1d293ced3786de1 Mon Sep 17 00:00:00 2001 From: TheXamlGuy Date: Thu, 18 Jul 2024 18:00:01 +0100 Subject: [PATCH] Fixed various issues --- Toolkit.Avalonia/ContentTemplate.cs | 65 ++++++++++++++++++- Toolkit.UI.Avalonia/ListBoxExtension.cs | 5 -- .../ListView/ListView.cs | 41 ++++++++++++ .../ListView/ListViewItem.cs | 10 +++ .../Overflow/Overflow.axaml | 2 + .../Overflow/Overflow.cs | 9 +++ .../Overflow/OverflowList.cs | 34 +++++----- .../Overflow/TemplateListBox.cs | 42 ------------ .../IItemContainerTemplateSelector.cs | 9 +++ 9 files changed, 152 insertions(+), 65 deletions(-) create mode 100644 Toolkit.UI.Controls.Avalonia/ListView/ListView.cs create mode 100644 Toolkit.UI.Controls.Avalonia/ListView/ListViewItem.cs delete mode 100644 Toolkit.UI.Controls.Avalonia/Overflow/TemplateListBox.cs create mode 100644 Toolkit.UI.Controls.Avalonia/Primitives/IItemContainerTemplateSelector.cs diff --git a/Toolkit.Avalonia/ContentTemplate.cs b/Toolkit.Avalonia/ContentTemplate.cs index cae6f8b..0a39bcc 100644 --- a/Toolkit.Avalonia/ContentTemplate.cs +++ b/Toolkit.Avalonia/ContentTemplate.cs @@ -1,14 +1,17 @@ using Avalonia.Controls; using Avalonia.Controls.Templates; +using Avalonia.Data; using Avalonia.Interactivity; using Microsoft.Extensions.DependencyInjection; using Toolkit.Foundation; +using Toolkit.UI.Controls.Avalonia; namespace Toolkit.Avalonia; public class ContentTemplate : IContentTemplate, - IDataTemplate + IDataTemplate, + IItemContainerTemplateSelector { public Control? Build(object? item) { @@ -71,4 +74,64 @@ public class ContentTemplate : } public bool Match(object? data) => true; + + public IDataTemplate? SelectTemplate(object? item, ItemsControl itemsControl) + { + if (item is IObservableViewModel observableViewModel) + { + if (observableViewModel.Provider is IServiceProvider provider) + { + Type itemType = item.GetType(); + if (provider.GetRequiredKeyedService(itemType.Name.Replace("ViewModel", "")) + is IContentTemplateDescriptor descriptor) + { + if (provider.GetRequiredKeyedService(descriptor.TemplateType, descriptor.Key) is Control control) + { + async void HandleLoaded(object? sender, RoutedEventArgs args) + { + control.Loaded -= HandleLoaded; + if (control.DataContext is object content) + { + if (content is IActivated activated) + { + await activated.OnActivated(); + } + } + } + + async void HandleDataContextChanged(object? sender, EventArgs args) + { + if (control.DataContext is object content) + { + if (content is IActivated activated) + { + await activated.OnActivated(); + } + } + } + + async void HandleUnloaded(object? sender, RoutedEventArgs args) + { + control.Unloaded -= HandleUnloaded; + if (control.DataContext is object content) + { + if (content is IDeactivated deactivated) + { + await deactivated.OnDeactivated(); + } + } + } + + control.Loaded += HandleLoaded; + control.Unloaded += HandleUnloaded; + control.DataContextChanged += HandleDataContextChanged; ; + + return new FuncDataTemplate(item.GetType(), (_, _) => control); + } + } + } + } + + return default; + } } \ No newline at end of file diff --git a/Toolkit.UI.Avalonia/ListBoxExtension.cs b/Toolkit.UI.Avalonia/ListBoxExtension.cs index 62e5fc0..250da31 100644 --- a/Toolkit.UI.Avalonia/ListBoxExtension.cs +++ b/Toolkit.UI.Avalonia/ListBoxExtension.cs @@ -39,11 +39,6 @@ public class ListBoxExtension } } - if (sender.DataContext == listBox.SelectedItem) - { - sender.RaiseEvent(new ItemInvokedEventArgs { RoutedEvent = ItemInvokedEvent }); - } - listBox.SelectionChanged += OnItemInvoked; return true; } diff --git a/Toolkit.UI.Controls.Avalonia/ListView/ListView.cs b/Toolkit.UI.Controls.Avalonia/ListView/ListView.cs new file mode 100644 index 0000000..1627250 --- /dev/null +++ b/Toolkit.UI.Controls.Avalonia/ListView/ListView.cs @@ -0,0 +1,41 @@ +using Avalonia; +using Avalonia.Controls; +using Avalonia.Controls.Templates; + +namespace Toolkit.UI.Controls.Avalonia; +public class ListView : + ListBox +{ + public static readonly StyledProperty ItemContainerTemplateSelectorProperty = + AvaloniaProperty.Register(nameof(ItemContainerTemplateSelector)); + + public IItemContainerTemplateSelector? ItemContainerTemplateSelector + { + get => GetValue(ItemContainerTemplateSelectorProperty); + set => SetValue(ItemContainerTemplateSelectorProperty, value); + } + + protected override Type StyleKeyOverride => + typeof(ListBox); + + protected override Control CreateContainerForItemOverride(object? item, int index, object? recycleKey) + { + if (ItemContainerTemplateSelector?.SelectTemplate(item, this) is IDataTemplate itemContainerTemplate) + { + if (itemContainerTemplate.Build(item) is ListViewItem container) + { + return container; + } + } + + return new ListViewItem(); + } + + protected override bool NeedsContainerOverride(object? item, + int index, + out object? recycleKey) + { + recycleKey = null; + return item is not ListViewItem; + } +} \ No newline at end of file diff --git a/Toolkit.UI.Controls.Avalonia/ListView/ListViewItem.cs b/Toolkit.UI.Controls.Avalonia/ListView/ListViewItem.cs new file mode 100644 index 0000000..3e66db3 --- /dev/null +++ b/Toolkit.UI.Controls.Avalonia/ListView/ListViewItem.cs @@ -0,0 +1,10 @@ +using Avalonia.Controls; + +namespace Toolkit.UI.Controls.Avalonia; + +public class ListViewItem : + ListBoxItem +{ + protected override Type StyleKeyOverride => + typeof(ListBoxItem); +} diff --git a/Toolkit.UI.Controls.Avalonia/Overflow/Overflow.axaml b/Toolkit.UI.Controls.Avalonia/Overflow/Overflow.axaml index 38204e7..9f2befc 100644 --- a/Toolkit.UI.Controls.Avalonia/Overflow/Overflow.axaml +++ b/Toolkit.UI.Controls.Avalonia/Overflow/Overflow.axaml @@ -162,6 +162,7 @@ @@ -197,6 +198,7 @@ diff --git a/Toolkit.UI.Controls.Avalonia/Overflow/Overflow.cs b/Toolkit.UI.Controls.Avalonia/Overflow/Overflow.cs index af8cfd9..30da7ca 100644 --- a/Toolkit.UI.Controls.Avalonia/Overflow/Overflow.cs +++ b/Toolkit.UI.Controls.Avalonia/Overflow/Overflow.cs @@ -14,6 +14,9 @@ namespace Toolkit.UI.Controls.Avalonia; public class Overflow : TemplatedControl { + public static readonly StyledProperty ItemContainerTemplateSelectorProperty = + AvaloniaProperty.Register(nameof(ItemContainerTemplateSelector)); + public static readonly StyledProperty> ItemsPanelProperty = AvaloniaProperty.Register>(nameof(ItemsPanel), new FuncTemplate(() => new StackPanel())); @@ -48,6 +51,12 @@ public class Overflow : .AddClassHandler(OnSecondarySelectionPropertyChanged); } + public IItemContainerTemplateSelector? ItemContainerTemplateSelector + { + get => GetValue(ItemContainerTemplateSelectorProperty); + set => SetValue(ItemContainerTemplateSelectorProperty, value); + } + public ITemplate ItemsPanel { get => GetValue(ItemsPanelProperty); diff --git a/Toolkit.UI.Controls.Avalonia/Overflow/OverflowList.cs b/Toolkit.UI.Controls.Avalonia/Overflow/OverflowList.cs index 4948d61..11fd0e2 100644 --- a/Toolkit.UI.Controls.Avalonia/Overflow/OverflowList.cs +++ b/Toolkit.UI.Controls.Avalonia/Overflow/OverflowList.cs @@ -1,4 +1,5 @@ -using Avalonia.Controls; +using Avalonia; +using Avalonia.Controls; using Avalonia.Controls.Templates; namespace Toolkit.UI.Controls.Avalonia; @@ -6,9 +7,18 @@ namespace Toolkit.UI.Controls.Avalonia; public class OverflowList : ListBox { + public static readonly StyledProperty ItemContainerTemplateSelectorProperty = + AvaloniaProperty.Register(nameof(ItemContainerTemplateSelector)); + + public IItemContainerTemplateSelector? ItemContainerTemplateSelector + { + get => GetValue(ItemContainerTemplateSelectorProperty); + set => SetValue(ItemContainerTemplateSelectorProperty, value); + } + protected override Control CreateContainerForItemOverride(object? item, int index, object? recycleKey) { - if (recycleKey is IDataTemplate itemContainerTemplate) + if (ItemContainerTemplateSelector?.SelectTemplate(item, this) is IDataTemplate itemContainerTemplate) { if (itemContainerTemplate.Build(item) is OverflowItem container) { @@ -19,21 +29,11 @@ public class OverflowList : return new OverflowItem(); } - protected override bool NeedsContainerOverride(object? item, int index, out object? recycleKey) + protected override bool NeedsContainerOverride(object? item, + int index, + out object? recycleKey) { - if (item is OverflowItem) - { - recycleKey = null; - return false; - } - - if (this.FindDataTemplate(item, ItemTemplate) is IDataTemplate itemContainerTemplate) - { - recycleKey = itemContainerTemplate; - return true; - } - - recycleKey = DefaultRecycleKey; - return true; + recycleKey = null; + return item is not OverflowItem; } } \ No newline at end of file diff --git a/Toolkit.UI.Controls.Avalonia/Overflow/TemplateListBox.cs b/Toolkit.UI.Controls.Avalonia/Overflow/TemplateListBox.cs deleted file mode 100644 index ae50a67..0000000 --- a/Toolkit.UI.Controls.Avalonia/Overflow/TemplateListBox.cs +++ /dev/null @@ -1,42 +0,0 @@ -using Avalonia.Controls; -using Avalonia.Controls.Templates; - -namespace Toolkit.UI.Controls.Avalonia; - -public class TemplateListBox : - ListBox -{ - protected override Type StyleKeyOverride => - typeof(ListBox); - - protected override Control CreateContainerForItemOverride(object? item, int index, object? recycleKey) - { - if (recycleKey is IDataTemplate itemContainerTemplate) - { - if (itemContainerTemplate.Build(item) is ListBoxItem container) - { - return container; - } - } - - return new ListBoxItem(); - } - - protected override bool NeedsContainerOverride(object? item, int index, out object? recycleKey) - { - if (item is ListBoxItem) - { - recycleKey = null; - return false; - } - - if (this.FindDataTemplate(item, ItemTemplate) is IDataTemplate itemContainerTemplate) - { - recycleKey = itemContainerTemplate; - return true; - } - - recycleKey = DefaultRecycleKey; - return true; - } -} \ No newline at end of file diff --git a/Toolkit.UI.Controls.Avalonia/Primitives/IItemContainerTemplateSelector.cs b/Toolkit.UI.Controls.Avalonia/Primitives/IItemContainerTemplateSelector.cs new file mode 100644 index 0000000..f8a0c89 --- /dev/null +++ b/Toolkit.UI.Controls.Avalonia/Primitives/IItemContainerTemplateSelector.cs @@ -0,0 +1,9 @@ +using Avalonia.Controls; +using Avalonia.Controls.Templates; + +namespace Toolkit.UI.Controls.Avalonia; + +public interface IItemContainerTemplateSelector +{ + IDataTemplate? SelectTemplate(object? item, ItemsControl itemsControl); +}