diff --git a/src/Avalonia.Controls/TreeView.cs b/src/Avalonia.Controls/TreeView.cs
index 78cd22ae32..03f6fd3aaa 100644
--- a/src/Avalonia.Controls/TreeView.cs
+++ b/src/Avalonia.Controls/TreeView.cs
@@ -392,14 +392,22 @@ namespace Avalonia.Controls
///
protected override IItemContainerGenerator CreateItemContainerGenerator()
{
- var result = new TreeItemContainerGenerator(
+ var result = CreateTreeItemContainerGenerator();
+ result.Index.Materialized += ContainerMaterialized;
+ return result;
+ }
+
+ protected virtual ITreeItemContainerGenerator CreateTreeItemContainerGenerator() =>
+ CreateTreeItemContainerGenerator();
+
+ protected virtual ITreeItemContainerGenerator CreateTreeItemContainerGenerator() where TVItem: TreeViewItem, new()
+ {
+ return new TreeItemContainerGenerator(
this,
TreeViewItem.HeaderProperty,
TreeViewItem.ItemTemplateProperty,
TreeViewItem.ItemsProperty,
TreeViewItem.IsExpandedProperty);
- result.Index.Materialized += ContainerMaterialized;
- return result;
}
///
diff --git a/src/Avalonia.Controls/TreeViewItem.cs b/src/Avalonia.Controls/TreeViewItem.cs
index 8ce258b546..88fb3cd9f1 100644
--- a/src/Avalonia.Controls/TreeViewItem.cs
+++ b/src/Avalonia.Controls/TreeViewItem.cs
@@ -92,9 +92,13 @@ namespace Avalonia.Controls
(ITreeItemContainerGenerator)base.ItemContainerGenerator;
///
- protected override IItemContainerGenerator CreateItemContainerGenerator()
+ protected override IItemContainerGenerator CreateItemContainerGenerator() => CreateTreeItemContainerGenerator();
+
+ ///
+ protected virtual ITreeItemContainerGenerator CreateTreeItemContainerGenerator()
+ where TVItem: TreeViewItem, new()
{
- return new TreeItemContainerGenerator(
+ return new TreeItemContainerGenerator(
this,
TreeViewItem.HeaderProperty,
TreeViewItem.ItemTemplateProperty,
diff --git a/tests/Avalonia.Controls.UnitTests/TreeViewTests.cs b/tests/Avalonia.Controls.UnitTests/TreeViewTests.cs
index 72ba3ab273..2169b15cad 100644
--- a/tests/Avalonia.Controls.UnitTests/TreeViewTests.cs
+++ b/tests/Avalonia.Controls.UnitTests/TreeViewTests.cs
@@ -6,6 +6,7 @@ using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using Avalonia.Collections;
+using Avalonia.Controls.Generators;
using Avalonia.Controls.Presenters;
using Avalonia.Controls.Templates;
using Avalonia.Data;
@@ -24,7 +25,7 @@ namespace Avalonia.Controls.UnitTests
public class TreeViewTests
{
MouseTestHelper _mouse = new MouseTestHelper();
-
+
[Fact]
public void Items_Should_Be_Created()
{
@@ -675,7 +676,7 @@ namespace Avalonia.Controls.UnitTests
Assert.Same(node, focus.Current);
}
}
-
+
[Fact]
public void Keyboard_Navigation_Should_Not_Crash_If_Selected_Item_Is_not_In_Tree()
{
@@ -1166,6 +1167,34 @@ namespace Avalonia.Controls.UnitTests
Assert.Empty(target.ItemContainerGenerator.Index.Containers);
}
+ [Fact]
+ public void Can_Use_Derived_TreeViewItem()
+ {
+ var tree = CreateTestTreeData();
+ var target = new DerivedTreeViewWithDerivedTreeViewItems
+ {
+ Template = CreateTreeViewTemplate(),
+ Items = tree,
+ };
+
+ ApplyTemplates(target);
+
+ // Verify that all items are DerivedTreeViewItem
+ VerifyItemType(target.ItemContainerGenerator);
+
+ void VerifyItemType(ITreeItemContainerGenerator containerGenerator)
+ {
+ foreach (var container in containerGenerator.Index.Containers)
+ {
+ var item = Assert.IsType(container);
+ if (item.ItemCount > 0)
+ {
+ VerifyItemType(item.ItemContainerGenerator);
+ }
+ }
+ }
+ }
+
private void ApplyTemplates(TreeView tree)
{
tree.ApplyTemplate();
@@ -1376,6 +1405,17 @@ namespace Avalonia.Controls.UnitTests
{
}
+ private class DerivedTreeViewWithDerivedTreeViewItems : TreeView
+ {
+ protected override ITreeItemContainerGenerator CreateTreeItemContainerGenerator() =>
+ CreateTreeItemContainerGenerator();
+ }
+
+ private class DerivedTreeViewItem : TreeViewItem
+ {
+ protected override IItemContainerGenerator CreateItemContainerGenerator() => CreateTreeItemContainerGenerator();
+ }
+
private class TestDataContext : INotifyPropertyChanged
{
private string _selectedItem;
@@ -1398,7 +1438,7 @@ namespace Avalonia.Controls.UnitTests
}
public event PropertyChangedEventHandler PropertyChanged;
-
+
}
}
}