Fixed various issues

This commit is contained in:
TheXamlGuy
2024-07-18 18:00:01 +01:00
parent 9010b3bf3c
commit e20890362e
9 changed files with 152 additions and 65 deletions
+64 -1
View File
@@ -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<IContentTemplateDescriptor>(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;
}
}
-5
View File
@@ -39,11 +39,6 @@ public class ListBoxExtension
}
}
if (sender.DataContext == listBox.SelectedItem)
{
sender.RaiseEvent(new ItemInvokedEventArgs { RoutedEvent = ItemInvokedEvent });
}
listBox.SelectionChanged += OnItemInvoked;
return true;
}
@@ -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<IItemContainerTemplateSelector?> ItemContainerTemplateSelectorProperty =
AvaloniaProperty.Register<ListView, IItemContainerTemplateSelector?>(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;
}
}
@@ -0,0 +1,10 @@
using Avalonia.Controls;
namespace Toolkit.UI.Controls.Avalonia;
public class ListViewItem :
ListBoxItem
{
protected override Type StyleKeyOverride =>
typeof(ListBoxItem);
}
@@ -162,6 +162,7 @@
<controls:OverflowList
x:Name="PrimaryListBox"
Grid.Column="0"
ItemContainerTemplateSelector="{TemplateBinding ItemContainerTemplateSelector}"
ItemTemplate="{TemplateBinding ItemTemplate}"
SelectedItem="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=TemplateSettings.PrimarySelection, Mode=TwoWay}">
<controls:OverflowList.ItemsPanel>
@@ -197,6 +198,7 @@
<Flyout>
<controls:OverflowList
x:Name="SecondaryListBox"
ItemContainerTemplateSelector="{TemplateBinding ItemContainerTemplateSelector}"
ItemTemplate="{TemplateBinding ItemTemplate}"
SelectedItem="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=TemplateSettings.SecondarySelection, Mode=TwoWay}">
<controls:OverflowList.ItemsPanel>
@@ -14,6 +14,9 @@ namespace Toolkit.UI.Controls.Avalonia;
public class Overflow :
TemplatedControl
{
public static readonly StyledProperty<IItemContainerTemplateSelector?> ItemContainerTemplateSelectorProperty =
AvaloniaProperty.Register<Overflow, IItemContainerTemplateSelector?>(nameof(ItemContainerTemplateSelector));
public static readonly StyledProperty<ITemplate<Panel?>> ItemsPanelProperty =
AvaloniaProperty.Register<Overflow, ITemplate<Panel?>>(nameof(ItemsPanel), new FuncTemplate<Panel?>(() => new StackPanel()));
@@ -48,6 +51,12 @@ public class Overflow :
.AddClassHandler<OverflowTemplateSettings>(OnSecondarySelectionPropertyChanged);
}
public IItemContainerTemplateSelector? ItemContainerTemplateSelector
{
get => GetValue(ItemContainerTemplateSelectorProperty);
set => SetValue(ItemContainerTemplateSelectorProperty, value);
}
public ITemplate<Panel?> ItemsPanel
{
get => GetValue(ItemsPanelProperty);
@@ -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<IItemContainerTemplateSelector?> ItemContainerTemplateSelectorProperty =
AvaloniaProperty.Register<OverflowList, IItemContainerTemplateSelector?>(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;
}
}
@@ -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;
}
}
@@ -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);
}