|
@@ -1,5 +1,8 @@
|
|
|
+using System;
|
|
|
using Avalonia.Collections;
|
|
|
using Avalonia.Controls.Presenters;
|
|
|
+using Avalonia.Controls.Templates;
|
|
|
+using Avalonia.Data;
|
|
|
using Avalonia.LogicalTree;
|
|
|
|
|
|
namespace Avalonia.Controls.Primitives
|
|
@@ -9,12 +12,21 @@ namespace Avalonia.Controls.Primitives
|
|
|
/// </summary>
|
|
|
public class HeaderedSelectingItemsControl : SelectingItemsControl, IContentPresenterHost
|
|
|
{
|
|
|
+ private IDisposable? _itemsBinding;
|
|
|
+ private ItemsControl? _prepareItemContainerOnAttach;
|
|
|
+
|
|
|
/// <summary>
|
|
|
/// Defines the <see cref="Header"/> property.
|
|
|
/// </summary>
|
|
|
public static readonly StyledProperty<object?> HeaderProperty =
|
|
|
HeaderedContentControl.HeaderProperty.AddOwner<HeaderedSelectingItemsControl>();
|
|
|
|
|
|
+ /// <summary>
|
|
|
+ /// Defines the <see cref="HeaderTemplate"/> property.
|
|
|
+ /// </summary>
|
|
|
+ public static readonly StyledProperty<IDataTemplate?> HeaderTemplateProperty =
|
|
|
+ HeaderedItemsControl.HeaderTemplateProperty.AddOwner<HeaderedSelectingItemsControl>();
|
|
|
+
|
|
|
/// <summary>
|
|
|
/// Initializes static members of the <see cref="ContentControl"/> class.
|
|
|
/// </summary>
|
|
@@ -32,6 +44,15 @@ namespace Avalonia.Controls.Primitives
|
|
|
set { SetValue(HeaderProperty, value); }
|
|
|
}
|
|
|
|
|
|
+ /// <summary>
|
|
|
+ /// Gets or sets the data template used to display the header content of the control.
|
|
|
+ /// </summary>
|
|
|
+ public IDataTemplate? HeaderTemplate
|
|
|
+ {
|
|
|
+ get => GetValue(HeaderTemplateProperty);
|
|
|
+ set => SetValue(HeaderTemplateProperty, value);
|
|
|
+ }
|
|
|
+
|
|
|
/// <summary>
|
|
|
/// Gets the header presenter from the control's template.
|
|
|
/// </summary>
|
|
@@ -50,6 +71,17 @@ namespace Avalonia.Controls.Primitives
|
|
|
return RegisterContentPresenter(presenter);
|
|
|
}
|
|
|
|
|
|
+ protected override void OnAttachedToLogicalTree(LogicalTreeAttachmentEventArgs e)
|
|
|
+ {
|
|
|
+ base.OnAttachedToLogicalTree(e);
|
|
|
+
|
|
|
+ if (_prepareItemContainerOnAttach is not null)
|
|
|
+ {
|
|
|
+ PrepareItemContainer(_prepareItemContainerOnAttach);
|
|
|
+ _prepareItemContainerOnAttach = null;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
/// <summary>
|
|
|
/// Called when an <see cref="IContentPresenter"/> is registered with the control.
|
|
|
/// </summary>
|
|
@@ -65,6 +97,37 @@ namespace Avalonia.Controls.Primitives
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
+ internal void PrepareItemContainer(ItemsControl parent)
|
|
|
+ {
|
|
|
+ _itemsBinding?.Dispose();
|
|
|
+ _itemsBinding = null;
|
|
|
+
|
|
|
+ var item = Header;
|
|
|
+
|
|
|
+ if (item is null)
|
|
|
+ {
|
|
|
+ _prepareItemContainerOnAttach = null;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ var headerTemplate = HeaderTemplate ?? parent.ItemTemplate;
|
|
|
+
|
|
|
+ if (headerTemplate is null)
|
|
|
+ {
|
|
|
+ if (((ILogical)this).IsAttachedToLogicalTree)
|
|
|
+ headerTemplate = this.FindDataTemplate(item);
|
|
|
+ else
|
|
|
+ _prepareItemContainerOnAttach = parent;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (headerTemplate is ITreeDataTemplate treeTemplate &&
|
|
|
+ treeTemplate.Match(item) &&
|
|
|
+ treeTemplate.ItemsSelector(item) is { } itemsBinding)
|
|
|
+ {
|
|
|
+ _itemsBinding = BindingOperations.Apply(this, ItemsSourceProperty, itemsBinding, null);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
private void HeaderChanged(AvaloniaPropertyChangedEventArgs e)
|
|
|
{
|
|
|
if (e.OldValue is ILogical oldChild)
|