TreeItemContainerGenerator.cs 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. // Copyright (c) The Avalonia Project. All rights reserved.
  2. // Licensed under the MIT license. See licence.md file in the project root for full license information.
  3. using System;
  4. using System.Collections.Generic;
  5. using Avalonia.Controls.Templates;
  6. using Avalonia.Data;
  7. namespace Avalonia.Controls.Generators
  8. {
  9. /// <summary>
  10. /// Creates containers for tree items and maintains a list of created containers.
  11. /// </summary>
  12. /// <typeparam name="T">The type of the container.</typeparam>
  13. public class TreeItemContainerGenerator<T> : ItemContainerGenerator<T>, ITreeItemContainerGenerator
  14. where T : class, IControl, new()
  15. {
  16. /// <summary>
  17. /// Initializes a new instance of the <see cref="TreeItemContainerGenerator{T}"/> class.
  18. /// </summary>
  19. /// <param name="owner">The owner control.</param>
  20. /// <param name="contentProperty">The container's Content property.</param>
  21. /// <param name="contentTemplateProperty">The container's ContentTemplate property.</param>
  22. /// <param name="itemsProperty">The container's Items property.</param>
  23. /// <param name="isExpandedProperty">The container's IsExpanded property.</param>
  24. /// <param name="index">The container index for the tree</param>
  25. public TreeItemContainerGenerator(
  26. IControl owner,
  27. AvaloniaProperty contentProperty,
  28. AvaloniaProperty contentTemplateProperty,
  29. AvaloniaProperty itemsProperty,
  30. AvaloniaProperty isExpandedProperty,
  31. TreeContainerIndex index)
  32. : base(owner, contentProperty, contentTemplateProperty)
  33. {
  34. Contract.Requires<ArgumentNullException>(owner != null);
  35. Contract.Requires<ArgumentNullException>(contentProperty != null);
  36. Contract.Requires<ArgumentNullException>(itemsProperty != null);
  37. Contract.Requires<ArgumentNullException>(isExpandedProperty != null);
  38. Contract.Requires<ArgumentNullException>(index != null);
  39. ItemsProperty = itemsProperty;
  40. IsExpandedProperty = isExpandedProperty;
  41. Index = index;
  42. }
  43. /// <summary>
  44. /// Gets the container index for the tree.
  45. /// </summary>
  46. public TreeContainerIndex Index { get; }
  47. /// <summary>
  48. /// Gets the item container's Items property.
  49. /// </summary>
  50. protected AvaloniaProperty ItemsProperty { get; }
  51. /// <summary>
  52. /// Gets the item container's IsExpanded property.
  53. /// </summary>
  54. protected AvaloniaProperty IsExpandedProperty { get; }
  55. /// <inheritdoc/>
  56. protected override IControl CreateContainer(object item)
  57. {
  58. var container = item as T;
  59. if (item == null)
  60. {
  61. return null;
  62. }
  63. else if (container != null)
  64. {
  65. Index.Add(item, container);
  66. return container;
  67. }
  68. else
  69. {
  70. var template = GetTreeDataTemplate(item, ItemTemplate);
  71. var result = new T();
  72. result.SetValue(ContentProperty, template.Build(item), BindingPriority.Style);
  73. var itemsSelector = template.ItemsSelector(item);
  74. if (itemsSelector != null)
  75. {
  76. BindingOperations.Apply(result, ItemsProperty, itemsSelector, null);
  77. }
  78. if (!(item is IControl))
  79. {
  80. result.DataContext = item;
  81. }
  82. NameScope.SetNameScope((Control)(object)result, new NameScope());
  83. Index.Add(item, result);
  84. return result;
  85. }
  86. }
  87. public override IEnumerable<ItemContainerInfo> Clear()
  88. {
  89. var items = base.Clear();
  90. Index.Remove(0, items);
  91. return items;
  92. }
  93. public override IEnumerable<ItemContainerInfo> Dematerialize(int startingIndex, int count)
  94. {
  95. Index.Remove(startingIndex, GetContainerRange(startingIndex, count));
  96. return base.Dematerialize(startingIndex, count);
  97. }
  98. public override IEnumerable<ItemContainerInfo> RemoveRange(int startingIndex, int count)
  99. {
  100. Index.Remove(startingIndex, GetContainerRange(startingIndex, count));
  101. return base.RemoveRange(startingIndex, count);
  102. }
  103. public override bool TryRecycle(int oldIndex, int newIndex, object item, IMemberSelector selector)
  104. {
  105. return false;
  106. }
  107. private ITreeDataTemplate GetTreeDataTemplate(object item, IDataTemplate primary)
  108. {
  109. var template = Owner.FindDataTemplate(item, primary) ?? FuncDataTemplate.Default;
  110. var treeTemplate = template as ITreeDataTemplate ??
  111. new FuncTreeDataTemplate(typeof(object), template.Build, x => null);
  112. return treeTemplate;
  113. }
  114. }
  115. }