diff --git a/src/Perspex.Controls/Generators/ITreeItemContainerGenerator.cs b/src/Perspex.Controls/Generators/ITreeItemContainerGenerator.cs
index 37f097618b..fa78433c57 100644
--- a/src/Perspex.Controls/Generators/ITreeItemContainerGenerator.cs
+++ b/src/Perspex.Controls/Generators/ITreeItemContainerGenerator.cs
@@ -11,23 +11,8 @@ namespace Perspex.Controls.Generators
public interface ITreeItemContainerGenerator : IItemContainerGenerator
{
///
- /// Gets the item container for the root of the tree, or null if this generator is itself
- /// the root of the tree.
+ /// Gets the container index for the tree.
///
- ITreeItemContainerGenerator RootGenerator { get; }
-
- ///
- /// Gets the item container for the specified item, anywhere in the tree.
- ///
- /// The item.
- /// The container, or null if not found.
- IControl TreeContainerFromItem(object item);
-
- ///
- /// Gets the item for the specified item container, anywhere in the tree.
- ///
- /// The container.
- /// The item, or null if not found.
- object TreeItemFromContainer(IControl container);
+ TreeContainerIndex Index { get; }
}
}
\ No newline at end of file
diff --git a/src/Perspex.Controls/Generators/TreeContainerIndex.cs b/src/Perspex.Controls/Generators/TreeContainerIndex.cs
new file mode 100644
index 0000000000..9de4ca1050
--- /dev/null
+++ b/src/Perspex.Controls/Generators/TreeContainerIndex.cs
@@ -0,0 +1,87 @@
+// Copyright (c) The Perspex Project. All rights reserved.
+// Licensed under the MIT license. See licence.md file in the project root for full license information.
+
+using System.Collections.Generic;
+
+namespace Perspex.Controls.Generators
+{
+ ///
+ /// Maintains an index of all item containers currently materialized by a .
+ ///
+ ///
+ /// Each has its own
+ /// that maintains the list of its direct children, but they also share an instance of this
+ /// class in their property which tracks
+ /// the containers materialized for the entire tree.
+ ///
+ public class TreeContainerIndex
+ {
+ private readonly Dictionary _itemToContainer = new Dictionary();
+ private readonly Dictionary _containerToItem = new Dictionary();
+
+ ///
+ /// Gets the currently materialized containers.
+ ///
+ public IEnumerable Items => _containerToItem.Keys;
+
+ ///
+ /// Adds an entry to the index.
+ ///
+ /// The item.
+ /// The item container.
+ public void Add(object item, IControl container)
+ {
+ _itemToContainer.Add(item, container);
+ _containerToItem.Add(container, item);
+ }
+
+ ///
+ /// Removes a container from the index.
+ ///
+ /// The item container.
+ public void Remove(IControl container)
+ {
+ var item = _containerToItem[container];
+ _containerToItem.Remove(container);
+ _itemToContainer.Remove(item);
+ }
+
+ ///
+ /// Removes a set of containers from the index.
+ ///
+ /// The item containers.
+ public void Remove(IEnumerable containers)
+ {
+ foreach (var container in containers)
+ {
+ var item = _containerToItem[container.ContainerControl];
+ _containerToItem.Remove(container.ContainerControl);
+ _itemToContainer.Remove(item);
+ }
+ }
+
+ ///
+ /// Gets the container for an item.
+ ///
+ /// The item.
+ /// The container, or null of not found.
+ public IControl ContainerFromItem(object item)
+ {
+ IControl result;
+ _itemToContainer.TryGetValue(item, out result);
+ return result;
+ }
+
+ ///
+ /// Gets the item for a container.
+ ///
+ /// The container.
+ /// The item, or null of not found.
+ public object ItemFromContainer(IControl container)
+ {
+ object result;
+ _containerToItem.TryGetValue(container, out result);
+ return result;
+ }
+ }
+}
diff --git a/src/Perspex.Controls/Generators/TreeItemContainerGenerator.cs b/src/Perspex.Controls/Generators/TreeItemContainerGenerator.cs
index 4caa53e3c1..0f2db6aa50 100644
--- a/src/Perspex.Controls/Generators/TreeItemContainerGenerator.cs
+++ b/src/Perspex.Controls/Generators/TreeItemContainerGenerator.cs
@@ -1,6 +1,7 @@
// Copyright (c) The Perspex Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
+using System;
using System.Collections;
using System.Collections.Generic;
using Perspex.Controls.Templates;
@@ -14,9 +15,6 @@ namespace Perspex.Controls.Generators
public class TreeItemContainerGenerator : ItemContainerGenerator, ITreeItemContainerGenerator
where T : class, IControl, new()
{
- private readonly Dictionary _itemToContainer;
- private readonly Dictionary _containerToItem;
-
///
/// Initializes a new instance of the class.
///
@@ -24,34 +22,30 @@ namespace Perspex.Controls.Generators
/// The container's Content property.
/// The container's Items property.
/// The container's IsExpanded property.
- ///
- /// The item container for the root of the tree, or null if this generator is itself the
- /// root of the tree.
- ///
+ /// The container index for the tree
public TreeItemContainerGenerator(
IControl owner,
PerspexProperty contentProperty,
PerspexProperty itemsProperty,
PerspexProperty isExpandedProperty,
- ITreeItemContainerGenerator rootGenerator)
+ TreeContainerIndex index)
: base(owner, contentProperty)
{
+ Contract.Requires(owner != null);
+ Contract.Requires(contentProperty != null);
+ Contract.Requires(itemsProperty != null);
+ Contract.Requires(isExpandedProperty != null);
+ Contract.Requires(index != null);
+
ItemsProperty = itemsProperty;
IsExpandedProperty = isExpandedProperty;
- RootGenerator = rootGenerator;
-
- if (rootGenerator == null)
- {
- _itemToContainer = new Dictionary();
- _containerToItem = new Dictionary();
- }
+ Index = index;
}
///
- /// Gets the item container for the root of the tree, or null if this generator is itself
- /// the root of the tree.
+ /// Gets the container index for the tree.
///
- public ITreeItemContainerGenerator RootGenerator { get; }
+ public TreeContainerIndex Index { get; }
///
/// Gets the item container's Items property.
@@ -63,30 +57,6 @@ namespace Perspex.Controls.Generators
///
protected PerspexProperty IsExpandedProperty { get; }
- ///
- /// Gets the item container for the specified item, anywhere in the tree.
- ///
- /// The item.
- /// The container, or null if not found.
- public IControl TreeContainerFromItem(object item)
- {
- T result;
- _itemToContainer.TryGetValue(item, out result);
- return result;
- }
-
- ///
- /// Gets the item for the specified item container, anywhere in the tree.
- ///
- /// The container.
- /// The item, or null if not found.
- public object TreeItemFromContainer(IControl container)
- {
- object result;
- _containerToItem.TryGetValue(container, out result);
- return result;
- }
-
///
protected override IControl CreateContainer(object item)
{
@@ -114,7 +84,7 @@ namespace Perspex.Controls.Generators
result.DataContext = item;
}
- AddToIndex(item, result);
+ Index.Add(item, result);
return result;
}
@@ -122,59 +92,17 @@ namespace Perspex.Controls.Generators
public override IEnumerable Clear()
{
- ClearIndex();
- return base.Clear();
+ var items = base.Clear();
+ Index.Remove(items);
+ return items;
}
public override IEnumerable Dematerialize(int startingIndex, int count)
{
- RemoveFromIndex(GetContainerRange(startingIndex, count));
+ Index.Remove(GetContainerRange(startingIndex, count));
return base.Dematerialize(startingIndex, count);
}
- private void AddToIndex(object item, T container)
- {
- if (RootGenerator != null)
- {
- ((TreeItemContainerGenerator)RootGenerator).AddToIndex(item, container);
- }
- else
- {
- _itemToContainer.Add(item, container);
- _containerToItem.Add(container, item);
- }
- }
-
- private void RemoveFromIndex(IEnumerable containers)
- {
- if (RootGenerator != null)
- {
- ((TreeItemContainerGenerator)RootGenerator).RemoveFromIndex(containers);
- }
- else
- {
- foreach (var container in containers)
- {
- var item = _containerToItem[container.ContainerControl];
- _containerToItem.Remove(container.ContainerControl);
- _itemToContainer.Remove(item);
- }
- }
- }
-
- private void ClearIndex()
- {
- if (RootGenerator != null)
- {
- ((TreeItemContainerGenerator)RootGenerator).ClearIndex();
- }
- else
- {
- _containerToItem.Clear();
- _itemToContainer.Clear();
- }
- }
-
///
/// Gets the data template for the specified item.
///
diff --git a/src/Perspex.Controls/Perspex.Controls.csproj b/src/Perspex.Controls/Perspex.Controls.csproj
index 0e8f07767e..c0fbb8fab3 100644
--- a/src/Perspex.Controls/Perspex.Controls.csproj
+++ b/src/Perspex.Controls/Perspex.Controls.csproj
@@ -46,6 +46,7 @@
+
diff --git a/src/Perspex.Controls/TreeView.cs b/src/Perspex.Controls/TreeView.cs
index 2dcb136526..4b7b1f986a 100644
--- a/src/Perspex.Controls/TreeView.cs
+++ b/src/Perspex.Controls/TreeView.cs
@@ -58,7 +58,7 @@ namespace Perspex.Controls
TreeViewItem.HeaderProperty,
TreeViewItem.ItemsProperty,
TreeViewItem.IsExpandedProperty,
- null);
+ new TreeContainerIndex());
}
///
@@ -101,13 +101,13 @@ namespace Perspex.Controls
bool rangeModifier = false,
bool toggleModifier = false)
{
- var item = ItemContainerGenerator.TreeItemFromContainer(container);
+ var item = ItemContainerGenerator.Index.ItemFromContainer(container);
if (item != null)
{
if (SelectedItem != null)
{
- var old = ItemContainerGenerator.TreeContainerFromItem(SelectedItem);
+ var old = ItemContainerGenerator.Index.ContainerFromItem(SelectedItem);
MarkContainerSelected(old, false);
}
@@ -162,7 +162,7 @@ namespace Perspex.Controls
if (item != null)
{
- if (item.ItemContainerGenerator.RootGenerator == this.ItemContainerGenerator)
+ if (item.ItemContainerGenerator.Index == this.ItemContainerGenerator.Index)
{
return item;
}
diff --git a/src/Perspex.Controls/TreeViewItem.cs b/src/Perspex.Controls/TreeViewItem.cs
index da263ca951..05cafe60ab 100644
--- a/src/Perspex.Controls/TreeViewItem.cs
+++ b/src/Perspex.Controls/TreeViewItem.cs
@@ -79,7 +79,7 @@ namespace Perspex.Controls
TreeViewItem.HeaderProperty,
TreeViewItem.ItemsProperty,
TreeViewItem.IsExpandedProperty,
- _treeView?.ItemContainerGenerator);
+ _treeView?.ItemContainerGenerator.Index ?? new TreeContainerIndex());
}
///
diff --git a/tests/Perspex.Controls.UnitTests/TreeViewTests.cs b/tests/Perspex.Controls.UnitTests/TreeViewTests.cs
index 06337d9412..627ab0d053 100644
--- a/tests/Perspex.Controls.UnitTests/TreeViewTests.cs
+++ b/tests/Perspex.Controls.UnitTests/TreeViewTests.cs
@@ -3,6 +3,7 @@
using System.Collections.Generic;
using System.Linq;
+using Perspex.Collections;
using Perspex.Controls.Presenters;
using Perspex.Controls.Templates;
using Perspex.Input;
@@ -65,7 +66,7 @@ namespace Perspex.Controls.UnitTests
ApplyTemplates(target);
- var container = target.ItemContainerGenerator.TreeContainerFromItem(
+ var container = target.ItemContainerGenerator.Index.ContainerFromItem(
tree[0].Children[1].Children[0]);
Assert.NotNull(container);
@@ -92,7 +93,7 @@ namespace Perspex.Controls.UnitTests
ApplyTemplates(target);
var item = tree[0].Children[1].Children[0];
- var container = (TreeViewItem)target.ItemContainerGenerator.TreeContainerFromItem(item);
+ var container = (TreeViewItem)target.ItemContainerGenerator.Index.ContainerFromItem(item);
Assert.NotNull(container);