diff --git a/Perspex.Controls/Generators/IItemContainerGenerator.cs b/Perspex.Controls/Generators/IItemContainerGenerator.cs
index 3f780dee40..d6762c4273 100644
--- a/Perspex.Controls/Generators/IItemContainerGenerator.cs
+++ b/Perspex.Controls/Generators/IItemContainerGenerator.cs
@@ -41,9 +41,9 @@ namespace Perspex.Controls.Generators
///
/// The index of the first item of the data in the containing collection.
///
- /// The number of items to remove.
+ /// The items.
/// The removed controls.
- IList RemoveContainers(int startingIndex, int count);
+ IList RemoveContainers(int startingIndex, IEnumerable items);
///
/// Clears the created containers from the index and returns the removed controls.
diff --git a/Perspex.Controls/Generators/ITreeItemContainerGenerator.cs b/Perspex.Controls/Generators/ITreeItemContainerGenerator.cs
new file mode 100644
index 0000000000..fca30cf94b
--- /dev/null
+++ b/Perspex.Controls/Generators/ITreeItemContainerGenerator.cs
@@ -0,0 +1,36 @@
+// -----------------------------------------------------------------------
+//
+// Copyright 2015 MIT Licence. See licence.md for more information.
+//
+// -----------------------------------------------------------------------
+
+namespace Perspex.Controls.Generators
+{
+ using System.Collections.Generic;
+
+ ///
+ /// Creates containers for tree items and maintains a list of created containers.
+ ///
+ public interface ITreeItemContainerGenerator : IItemContainerGenerator
+ {
+ ///
+ /// Gets all of the generated container controls.
+ ///
+ /// The containers.
+ IEnumerable GetAllContainers();
+
+ ///
+ /// Gets the item that is contained by the specified container.
+ ///
+ /// The container.
+ /// The item.
+ object ItemFromContainer(IControl container);
+
+ ///
+ /// Gets the container for the specified item
+ ///
+ /// The item.
+ /// The container.
+ IControl ContainerFromItem(object item);
+ }
+}
\ No newline at end of file
diff --git a/Perspex.Controls/Generators/ItemContainerGenerator.cs b/Perspex.Controls/Generators/ItemContainerGenerator.cs
index af00571602..a899986d22 100644
--- a/Perspex.Controls/Generators/ItemContainerGenerator.cs
+++ b/Perspex.Controls/Generators/ItemContainerGenerator.cs
@@ -20,7 +20,7 @@ namespace Perspex.Controls.Generators
{
private Dictionary containers = new Dictionary();
- private Subject containersInitialized;
+ private Subject containersInitialized = new Subject();
///
/// Initializes a new instance of the class.
@@ -29,7 +29,6 @@ namespace Perspex.Controls.Generators
public ItemContainerGenerator(IControl owner)
{
this.Owner = owner;
- this.containersInitialized = new Subject();
}
///
@@ -79,11 +78,12 @@ namespace Perspex.Controls.Generators
///
/// The index of the first item of the data in the containing collection.
///
- /// The number of items to remove.
+ /// The items.
/// The removed controls.
- public IList RemoveContainers(int startingIndex, int count)
+ public IList RemoveContainers(int startingIndex, IEnumerable items)
{
var result = new List();
+ var count = items.Cast().Count();
for (int i = startingIndex; i < startingIndex + count; ++i)
{
diff --git a/Perspex.Controls/Generators/TreeItemContainerGenerator.cs b/Perspex.Controls/Generators/TreeItemContainerGenerator.cs
index dae0913e25..f35d93aa95 100644
--- a/Perspex.Controls/Generators/TreeItemContainerGenerator.cs
+++ b/Perspex.Controls/Generators/TreeItemContainerGenerator.cs
@@ -1,6 +1,6 @@
// -----------------------------------------------------------------------
//
-// Copyright 2014 MIT Licence. See licence.md for more information.
+// Copyright 2015 MIT Licence. See licence.md for more information.
//
// -----------------------------------------------------------------------
@@ -10,84 +10,223 @@ namespace Perspex.Controls.Generators
using System.Collections;
using System.Collections.Generic;
using System.Linq;
+ using System.Reactive.Subjects;
using Perspex.Controls.Templates;
- public class TreeItemContainerGenerator : ItemContainerGenerator, IItemContainerGenerator where T : TreeViewItem, new()
+ ///
+ /// Creates containers for tree items and maintains a list of created containers.
+ ///
+ /// The type of the container.
+ public class TreeItemContainerGenerator : ITreeItemContainerGenerator where T : TreeViewItem, new()
{
- public TreeItemContainerGenerator(ItemsControl owner)
- : base(owner)
+ private Dictionary containers = new Dictionary();
+
+ private Subject containersInitialized = new Subject();
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The owner control.
+ public TreeItemContainerGenerator(IControl owner)
+ {
+ this.Owner = owner;
+ }
+
+ ///
+ /// Signalled whenever new containers are initialized.
+ ///
+ public IObservable ContainersInitialized => this.containersInitialized;
+
+ ///
+ /// Gets the owner control.
+ ///
+ public IControl Owner { get; }
+
+ ///
+ /// Creates container controls for a collection of items.
+ ///
+ ///
+ /// The index of the first item of the data in the containing collection.
+ ///
+ /// The items.
+ /// An optional item template.
+ /// The created container controls.
+ public IList CreateContainers(int startingIndex, IEnumerable items, IDataTemplate itemTemplate)
{
+ Contract.Requires(items != null);
+
+ int index = startingIndex;
+ var result = new List();
+
+ foreach (var item in items)
+ {
+ var container = this.CreateContainer(item, itemTemplate);
+ this.containers.Add(item, container);
+ result.Add(container);
+ }
+
+ this.containersInitialized.OnNext(new ItemContainers(startingIndex, result));
+
+ return result.Where(x => x != null).ToList();
}
- ////IEnumerable IItemContainerGenerator.Remove(IEnumerable items)
- ////{
- //// throw new NotImplementedException();
- //// var result = new List();
-
- //// foreach (var item in items)
- //// {
- //// var container = (T)this.GetContainerForItem(item);
- //// this.Remove(container, result);
- //// }
-
- //// return result;
- ////}
-
- ////protected override Control CreateContainerOverride(object item)
- ////{
- //// T result = item as T;
-
- //// if (result == null)
- //// {
- //// TreeDataTemplate template = this.GetTreeDataTemplate(item);
-
- //// result = new T
- //// {
- //// Header = template.Build(item),
- //// Items = template.ItemsSelector(item),
- //// IsExpanded = template.IsExpanded(item),
- //// };
- //// }
-
- //// return result;
- ////}
-
- ////private TreeDataTemplate GetTreeDataTemplate(object item)
- ////{
- //// IDataTemplate template = this.Owner.FindDataTemplate(item);
-
- //// if (template == null)
- //// {
- //// template = DataTemplate.Default;
- //// }
-
- //// TreeDataTemplate treeTemplate = template as TreeDataTemplate;
-
- //// if (treeTemplate == null)
- //// {
- //// treeTemplate = new TreeDataTemplate(template.Build, x => null);
- //// }
-
- //// return treeTemplate;
- ////}
-
- ////private void Remove(T container, List removed)
- ////{
- //// if (container.Items != null)
- //// {
- //// foreach (var childItem in container.Items)
- //// {
- //// var childContainer = (T)this.GetContainerForItem(childItem);
-
- //// if (childContainer != null)
- //// {
- //// this.Remove(childContainer, removed);
- //// }
- //// }
- //// }
-
- //// this.RemoveByContainerInternal(container);
- //// removed.Add(container);
- ////}
+ ///
+ /// Removes a set of created containers from the index and returns the removed controls.
+ ///
+ ///
+ /// The index of the first item of the data in the containing collection.
+ ///
+ /// The items.
+ /// The removed controls.
+ public IList RemoveContainers(int startingIndex, IEnumerable items)
+ {
+ var result = new List();
+
+ foreach (var item in items)
+ {
+ T container;
+
+ if (this.containers.TryGetValue(item, out container))
+ {
+ this.Remove(container, result);
+ }
+ }
+
+ return result;
+ }
+
+ ///
+ /// Clears the created containers from the index and returns the removed controls.
+ ///
+ /// The removed controls.
+ public IList ClearContainers()
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Gets the container control representing the item with the specified index.
+ ///
+ /// The index.
+ /// The container or null if no container created.
+ public IControl ContainerFromIndex(int index)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Gets the index of the specified container control.
+ ///
+ /// The container.
+ /// The index of the container or -1 if not found.
+ public int IndexFromContainer(IControl container)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Gets all of the generated container controls.
+ ///
+ /// The containers.
+ public IEnumerable GetAllContainers()
+ {
+ return this.containers.Values;
+ }
+
+ ///
+ /// Gets the item that is contained by the specified container.
+ ///
+ /// The container.
+ /// The item.
+ public object ItemFromContainer(IControl container)
+ {
+ return container.DataContext;
+ }
+
+ ///
+ /// Gets the container for the specified item
+ ///
+ /// The item.
+ /// The container.
+ public IControl ContainerFromItem(object item)
+ {
+ T result;
+ this.containers.TryGetValue(item, out result);
+ return result;
+ }
+
+ ///
+ /// Creates the container for an item.
+ ///
+ /// The item.
+ /// An optional item template.
+ /// The created container control.
+ protected virtual T CreateContainer(object item, IDataTemplate itemTemplate)
+ {
+ T result = item as T;
+
+ if (result == null)
+ {
+ var template = this.GetTreeDataTemplate(item);
+
+ result = new T
+ {
+ Header = template.Build(item),
+ Items = template.ItemsSelector(item),
+ IsExpanded = template.IsExpanded(item),
+ DataContext = item,
+ };
+ }
+
+ return result;
+ }
+
+ ///
+ /// Gets the data template for the specified item.
+ ///
+ /// The item.
+ /// The template.
+ private ITreeDataTemplate GetTreeDataTemplate(object item)
+ {
+ IDataTemplate template = this.Owner.FindDataTemplate(item);
+
+ if (template == null)
+ {
+ template = DataTemplate.Default;
+ }
+
+ var treeTemplate = template as ITreeDataTemplate;
+
+ if (treeTemplate == null)
+ {
+ treeTemplate = new TreeDataTemplate(typeof(object), template.Build, x => null);
+ }
+
+ return treeTemplate;
+ }
+
+ private void Remove(T container, IList removed)
+ {
+ if (container.Items != null)
+ {
+ foreach (var childItem in container.Items)
+ {
+ T childContainer;
+
+ if (this.containers.TryGetValue(childItem, out childContainer))
+ {
+ this.Remove(childContainer, removed);
+ }
+ }
+ }
+
+ // TODO: Dual index.
+ var i = this.containers.FirstOrDefault(x => x.Value == container);
+
+ if (i.Key != null)
+ {
+ this.containers.Remove(i.Key);
+ }
+ }
}
}
diff --git a/Perspex.Controls/Perspex.Controls.csproj b/Perspex.Controls/Perspex.Controls.csproj
index ea0d640022..c7e5ef8680 100644
--- a/Perspex.Controls/Perspex.Controls.csproj
+++ b/Perspex.Controls/Perspex.Controls.csproj
@@ -36,6 +36,7 @@
4
+
@@ -115,6 +116,8 @@
+
+
@@ -141,7 +144,7 @@
-
+
diff --git a/Perspex.Controls/Presenters/DeckPresenter.cs b/Perspex.Controls/Presenters/DeckPresenter.cs
index 899cf86140..1c8ba52c18 100644
--- a/Perspex.Controls/Presenters/DeckPresenter.cs
+++ b/Perspex.Controls/Presenters/DeckPresenter.cs
@@ -194,7 +194,7 @@ namespace Perspex.Controls.Presenters
if (from != null)
{
this.Panel.Children.Remove(from);
- generator.RemoveContainers(fromIndex, 1);
+ generator.RemoveContainers(fromIndex, new[] { from });
}
}
diff --git a/Perspex.Controls/Presenters/ItemsPresenter.cs b/Perspex.Controls/Presenters/ItemsPresenter.cs
index 445568fb95..2b16212e1c 100644
--- a/Perspex.Controls/Presenters/ItemsPresenter.cs
+++ b/Perspex.Controls/Presenters/ItemsPresenter.cs
@@ -210,7 +210,7 @@ namespace Perspex.Controls.Presenters
case NotifyCollectionChangedAction.Remove:
this.Panel.Children.RemoveAll(
- generator.RemoveContainers(e.OldStartingIndex, e.OldItems.Count));
+ generator.RemoveContainers(e.OldStartingIndex, e.OldItems));
break;
}
diff --git a/Perspex.Controls/Templates/ITreeDataTemplate.cs b/Perspex.Controls/Templates/ITreeDataTemplate.cs
new file mode 100644
index 0000000000..0b0fb8af8a
--- /dev/null
+++ b/Perspex.Controls/Templates/ITreeDataTemplate.cs
@@ -0,0 +1,30 @@
+// -----------------------------------------------------------------------
+//
+// Copyright 2014 MIT Licence. See licence.md for more information.
+//
+// -----------------------------------------------------------------------
+
+namespace Perspex.Controls.Templates
+{
+ using System.Collections;
+
+ ///
+ /// Interface representing a template used to build hierachical data.
+ ///
+ public interface ITreeDataTemplate : IDataTemplate
+ {
+ ///
+ /// Checks to see if the item should be initially expanded.
+ ///
+ /// The item.
+ /// True if the item should be initially expanded, otherwise false.
+ bool IsExpanded(object item);
+
+ ///
+ /// Selects the child items of an item.
+ ///
+ /// The item.
+ /// The child items, or null if no child items.
+ IEnumerable ItemsSelector(object item);
+ }
+}
\ No newline at end of file
diff --git a/Perspex.Controls/Templates/TreeDataTemplate.cs b/Perspex.Controls/Templates/TreeDataTemplate.cs
new file mode 100644
index 0000000000..86e184aaf9
--- /dev/null
+++ b/Perspex.Controls/Templates/TreeDataTemplate.cs
@@ -0,0 +1,148 @@
+// -----------------------------------------------------------------------
+//
+// Copyright 2014 MIT Licence. See licence.md for more information.
+//
+// -----------------------------------------------------------------------
+
+namespace Perspex.Controls.Templates
+{
+ using System;
+ using System.Collections;
+ using System.Reflection;
+
+ ///
+ /// A template used to build hierachical data.
+ ///
+ public class TreeDataTemplate : DataTemplate, ITreeDataTemplate
+ {
+ private Func itemsSelector;
+
+ private Func isExpanded;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The type of data which the data template matches.
+ ///
+ /// A function which when passed an object of returns a control.
+ ///
+ ///
+ /// A function which when passed an object of returns the child
+ /// items.
+ ///
+ public TreeDataTemplate(
+ Type type,
+ Func build,
+ Func itemsSelector)
+ : this(o => IsInstance(o, type), build, itemsSelector)
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The type of data which the data template matches.
+ ///
+ /// A function which when passed an object of returns a control.
+ ///
+ ///
+ /// A function which when passed an object of returns the child
+ /// items.
+ ///
+ ///
+ /// A function which when passed an object of returns the the
+ /// initial expanded state of the node.
+ ///
+ public TreeDataTemplate(
+ Type type,
+ Func build,
+ Func itemsSelector,
+ Func isExpanded)
+ : this(o => IsInstance(o, type), build, itemsSelector, isExpanded)
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ ///
+ /// A function which determines whether the data template matches the specified data.
+ ///
+ ///
+ /// A function which when passed a matching object returns a control.
+ ///
+ ///
+ /// A function which when passed a matching object returns the child items.
+ ///
+ public TreeDataTemplate(
+ Func match,
+ Func build,
+ Func itemsSelector)
+ : this(match, build, itemsSelector, _ => false)
+ {
+ this.itemsSelector = itemsSelector;
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ ///
+ /// A function which determines whether the data template matches the specified data.
+ ///
+ ///
+ /// A function which when passed a matching object returns a control.
+ ///
+ ///
+ /// A function which when passed a matching object returns the child items.
+ ///
+ ///
+ /// A function which when passed a matching object returns the the initial expanded state
+ /// of the node.
+ ///
+ public TreeDataTemplate(
+ Func match,
+ Func build,
+ Func itemsSelector,
+ Func isExpanded)
+ : base(match, build)
+ {
+ this.itemsSelector = itemsSelector;
+ this.isExpanded = isExpanded;
+ }
+
+ ///
+ /// Checks to see if the item should be initially expanded.
+ ///
+ /// The item.
+ /// True if the item should be initially expanded, otherwise false.
+ public bool IsExpanded(object item)
+ {
+ return this?.isExpanded(item) ?? false;
+ }
+
+ ///
+ /// Selects the child items of an item.
+ ///
+ /// The item.
+ /// The child items, or null if no child items.
+ public IEnumerable ItemsSelector(object item)
+ {
+ return this?.itemsSelector(item);
+ }
+
+ ///
+ /// Determines of an object is of the specified type.
+ ///
+ /// The object.
+ /// The type.
+ ///
+ /// True if is of type , otherwise false.
+ ///
+ private static bool IsInstance(object o, Type t)
+ {
+ return (o != null) ?
+ t.GetTypeInfo().IsAssignableFrom(o.GetType().GetTypeInfo()) :
+ false;
+ }
+ }
+}
diff --git a/Perspex.Controls/Templates/TreeDataTemplate`1.cs b/Perspex.Controls/Templates/TreeDataTemplate`1.cs
new file mode 100644
index 0000000000..59eddf840b
--- /dev/null
+++ b/Perspex.Controls/Templates/TreeDataTemplate`1.cs
@@ -0,0 +1,137 @@
+// -----------------------------------------------------------------------
+//
+// Copyright 2014 MIT Licence. See licence.md for more information.
+//
+// -----------------------------------------------------------------------
+
+namespace Perspex.Controls.Templates
+{
+ using System;
+ using System.Collections;
+
+ ///
+ /// A template used to build hierachical data.
+ ///
+ /// The type of the template's data.
+ public class TreeDataTemplate : TreeDataTemplate
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ ///
+ /// A function which when passed an object of returns a control.
+ ///
+ ///
+ /// A function which when passed an object of returns the child
+ /// items.
+ ///
+ public TreeDataTemplate(
+ Func build,
+ Func itemsSelector)
+ : base(
+ typeof(T),
+ TreeDataTemplate.Cast(build),
+ TreeDataTemplate.Cast(itemsSelector))
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ ///
+ /// A function which when passed an object of returns a control.
+ ///
+ ///
+ /// A function which when passed an object of returns the child
+ /// items.
+ ///
+ ///
+ /// A function which when passed an object of returns the the
+ /// initial expanded state of the node.
+ ///
+ public TreeDataTemplate(
+ Func build,
+ Func itemsSelector,
+ Func isExpanded)
+ : base(
+ typeof(T),
+ TreeDataTemplate.Cast(build),
+ TreeDataTemplate.Cast(itemsSelector),
+ TreeDataTemplate.Cast(isExpanded))
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ ///
+ /// A function which determines whether the data template matches the specified data.
+ ///
+ ///
+ /// A function which when passed a matching object returns a control.
+ ///
+ ///
+ /// A function which when passed a matching object returns the child items.
+ ///
+ public TreeDataTemplate(
+ Func match,
+ Func build,
+ Func itemsSelector)
+ : base(
+ TreeDataTemplate.CastMatch(match),
+ TreeDataTemplate.Cast(build),
+ TreeDataTemplate.Cast(itemsSelector))
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ ///
+ /// A function which determines whether the data template matches the specified data.
+ ///
+ ///
+ /// A function which when passed a matching object returns a control.
+ ///
+ ///
+ /// A function which when passed a matching object returns the child items.
+ ///
+ ///
+ /// A function which when passed a matching object returns the the initial expanded state
+ /// of the node.
+ ///
+ public TreeDataTemplate(
+ Func match,
+ Func build,
+ Func itemsSelector,
+ Func isExpanded)
+ : base(
+ TreeDataTemplate.CastMatch(match),
+ TreeDataTemplate.Cast(build),
+ TreeDataTemplate.Cast(itemsSelector),
+ TreeDataTemplate.Cast(isExpanded))
+ {
+ }
+
+ ///
+ /// Casts a typed match function to an untyped match function.
+ ///
+ /// The typed function.
+ /// The untyped function.
+ private static Func CastMatch(Func f)
+ {
+ return o => (o is T) ? f((T)o) : false;
+ }
+
+ ///
+ /// Casts a function with a typed parameter to an untyped function.
+ ///
+ /// The result.
+ /// The typed function.
+ /// The untyped function.
+ private static Func Cast(Func f)
+ {
+ return o => f((T)o);
+ }
+ }
+}
diff --git a/Perspex.Controls/TreeDataTemplate.cs b/Perspex.Controls/TreeDataTemplate.cs
deleted file mode 100644
index eec4bcf5af..0000000000
--- a/Perspex.Controls/TreeDataTemplate.cs
+++ /dev/null
@@ -1,138 +0,0 @@
-// -----------------------------------------------------------------------
-//
-// Copyright 2014 MIT Licence. See licence.md for more information.
-//
-// -----------------------------------------------------------------------
-
-namespace Perspex.Controls
-{
- using System;
- using System.Collections;
- using System.Reflection;
- using Perspex.Controls.Templates;
-
- public class TreeDataTemplate : DataTemplate
- {
- public TreeDataTemplate(
- Func build,
- Func itemsSelector)
- : this(o => true, build, itemsSelector)
- {
- }
-
- public TreeDataTemplate(
- Type type,
- Func build,
- Func itemsSelector)
- : this(o => IsInstance(o, type), build, itemsSelector)
- {
- }
-
- public TreeDataTemplate(
- Type type,
- Func build,
- Func itemsSelector,
- Func isExpanded)
- : this(o => IsInstance(o, type), build, itemsSelector, isExpanded)
- {
- }
-
- public TreeDataTemplate(
- Func match,
- Func build,
- Func itemsSelector)
- : this(match, build, itemsSelector, _ => false)
- {
- this.ItemsSelector = itemsSelector;
- }
-
- public TreeDataTemplate(
- Func match,
- Func build,
- Func itemsSelector,
- Func isExpanded)
- : base(match, build)
- {
- this.ItemsSelector = itemsSelector;
- this.IsExpanded = isExpanded;
- }
-
- public Func ItemsSelector { get; private set; }
-
- public Func IsExpanded { get; private set; }
-
- ///
- /// Determines of an object is of the specified type.
- ///
- /// The object.
- /// The type.
- ///
- /// True if is of type , otherwise false.
- ///
- private static bool IsInstance(object o, Type t)
- {
- return (o != null) ?
- t.GetTypeInfo().IsAssignableFrom(o.GetType().GetTypeInfo()) :
- false;
- }
- }
-
- public class TreeDataTemplate : TreeDataTemplate
- {
- public TreeDataTemplate(
- Func build,
- Func itemsSelector)
- : base(
- typeof(T),
- TreeDataTemplate.Cast(build),
- TreeDataTemplate.Cast(itemsSelector))
- {
- }
-
- public TreeDataTemplate(
- Func build,
- Func itemsSelector,
- Func isExpanded)
- : base(
- typeof(T),
- TreeDataTemplate.Cast(build),
- TreeDataTemplate.Cast(itemsSelector),
- TreeDataTemplate.Cast(isExpanded))
- {
- }
-
- public TreeDataTemplate(
- Func match,
- Func build,
- Func itemsSelector)
- : base(
- TreeDataTemplate.CastMatch(match),
- TreeDataTemplate.Cast(build),
- TreeDataTemplate.Cast(itemsSelector))
- {
- }
-
- public TreeDataTemplate(
- Func match,
- Func build,
- Func itemsSelector,
- Func isExpanded)
- : base(
- TreeDataTemplate.CastMatch(match),
- TreeDataTemplate.Cast(build),
- TreeDataTemplate.Cast(itemsSelector),
- TreeDataTemplate.Cast(isExpanded))
- {
- }
-
- private static Func CastMatch(Func f)
- {
- return o => (o is T) ? f((T)o) : false;
- }
-
- private static Func Cast(Func f)
- {
- return o => f((T)o);
- }
- }
-}
diff --git a/Perspex.Controls/TreeView.cs b/Perspex.Controls/TreeView.cs
index 25b1afa151..ca1123597c 100644
--- a/Perspex.Controls/TreeView.cs
+++ b/Perspex.Controls/TreeView.cs
@@ -17,7 +17,7 @@ namespace Perspex.Controls
public class TreeView : ItemsControl
{
public static readonly PerspexProperty SelectedItemProperty =
- PerspexProperty.Register("SelectedItem", validate: ValidateSelectedItem);
+ PerspexProperty.Register("SelectedItem");
static TreeView()
{
@@ -32,6 +32,11 @@ namespace Perspex.Controls
});
}
+ public new ITreeItemContainerGenerator ItemContainerGenerator
+ {
+ get { return (ITreeItemContainerGenerator)base.ItemContainerGenerator; }
+ }
+
public object SelectedItem
{
get { return this.GetValue(SelectedItemProperty); }
@@ -43,178 +48,45 @@ namespace Perspex.Controls
return new TreeItemContainerGenerator(this);
}
- protected virtual void MoveSelection(FocusNavigationDirection direction)
- {
- // TODO: Up and down movement is a *HACK* and probably pretty slow. Probably needs
- // rewriting at some point.
- ////if (this.SelectedItem != null)
- ////{
- //// switch (direction)
- //// {
- //// case FocusNavigationDirection.Up:
- //// {
- //// var list = this.Flatten();
- //// var index = list.IndexOf(this.SelectedItem);
-
- //// if (index > 0)
- //// {
- //// this.SelectedItem = list[index - 1];
- //// }
-
- //// break;
- //// }
-
- //// case FocusNavigationDirection.Down:
- //// {
- //// var list = this.Flatten();
- //// var index = list.IndexOf(this.SelectedItem);
-
- //// if (index + 1 < list.Count)
- //// {
- //// this.SelectedItem = list[index + 1];
- //// }
-
- //// break;
- //// }
-
- //// case FocusNavigationDirection.Left:
- //// {
- //// var node = (TreeViewItem)this.ItemContainerGenerator.GetContainerForItem(this.SelectedItem);
- //// node.IsExpanded = false;
- //// break;
- //// }
-
- //// case FocusNavigationDirection.Right:
- //// {
- //// var node = (TreeViewItem)this.ItemContainerGenerator.GetContainerForItem(this.SelectedItem);
- //// node.IsExpanded = true;
- //// break;
- //// }
- //// }
- ////}
- }
-
- protected override void OnKeyDown(KeyEventArgs e)
- {
- ////base.OnKeyDown(e);
-
- ////if (!e.Handled)
- ////{
- //// switch (e.Key)
- //// {
- //// case Key.Up:
- //// this.MoveSelection(FocusNavigationDirection.Up);
- //// break;
- //// case Key.Down:
- //// this.MoveSelection(FocusNavigationDirection.Down);
- //// break;
- //// case Key.Left:
- //// this.MoveSelection(FocusNavigationDirection.Left);
- //// break;
- //// case Key.Right:
- //// this.MoveSelection(FocusNavigationDirection.Right);
- //// break;
- //// default:
- //// return;
- //// }
-
- //// var selected = this.SelectedItem;
-
- //// if (selected != null)
- //// {
- //// var container = this.ItemContainerGenerator.GetContainerForItem(selected);
-
- //// if (container != null)
- //// {
- //// container.BringIntoView();
- //// FocusManager.Instance.Focus(container, true);
- //// }
- //// }
-
- //// e.Handled = true;
- ////}
- }
-
protected override void OnPointerPressed(PointerPressEventArgs e)
{
- ////IVisual source = (IVisual)e.Source;
- ////var selectable = source.GetVisualAncestors()
- //// .OfType()
- //// .OfType()
- //// .FirstOrDefault();
-
- ////if (selectable != null)
- ////{
- //// var item = this.ItemContainerGenerator.GetItemForContainer(selectable);
-
- //// if (item != null)
- //// {
- //// this.SelectedItem = item;
- //// selectable.BringIntoView();
- //// FocusManager.Instance.Focus(selectable);
- //// }
- ////}
-
- ////e.Handled = true;
- }
-
- private static object ValidateSelectedItem(PerspexObject o, object value)
- {
- //var control = o as SelectingItemsControl;
+ IVisual source = (IVisual)e.Source;
+ var selectable = source.GetVisualAncestors()
+ .OfType()
+ .OfType()
+ .FirstOrDefault();
- //if (control != null)
- //{
- // if (value != null && (control.Items == null || control.Items.IndexOf(value) == -1))
- // {
- // return null;
- // }
- //}
-
- return value;
- }
-
- private List Flatten()
- {
- var result = new List();
- this.Flatten(this.Items, result);
- return result;
- }
+ if (selectable != null)
+ {
+ var item = this.ItemContainerGenerator.ItemFromContainer(selectable);
- private void Flatten(IEnumerable items, List result)
- {
- ////if (items != null)
- ////{
- //// foreach (object item in items)
- //// {
- //// var container = (TreeViewItem)this.ItemContainerGenerator.GetContainerForItem(item);
- //// result.Add(item);
+ if (item != null)
+ {
+ this.SelectedItem = item;
+ selectable.BringIntoView();
+ FocusManager.Instance.Focus(selectable);
+ }
+ }
- //// if (container.IsExpanded)
- //// {
- //// this.Flatten(container.Items, result);
- //// }
- //// }
- ////}
+ e.Handled = true;
}
private void SelectedItemChanged(object selected)
{
- ////var containers = this.ItemContainerGenerator.GetAll()
- //// .Select(x => x.Item2)
- //// .OfType();
- ////var selectedContainer = (selected != null) ?
- //// this.ItemContainerGenerator.GetContainerForItem(selected) :
- //// null;
+ var containers = this.ItemContainerGenerator.GetAllContainers().OfType();
+ var selectedContainer = (selected != null) ?
+ this.ItemContainerGenerator.ContainerFromItem(selected) :
+ null;
- ////if (this.Presenter != null && this.Presenter.Panel != null)
- ////{
- //// KeyboardNavigation.SetTabOnceActiveElement(this.Presenter.Panel, selectedContainer);
- ////}
+ if (this.Presenter != null && this.Presenter.Panel != null)
+ {
+ KeyboardNavigation.SetTabOnceActiveElement(this.Presenter.Panel, selectedContainer);
+ }
- ////foreach (var item in containers)
- ////{
- //// item.IsSelected = item == selectedContainer;
- ////}
+ foreach (var item in containers)
+ {
+ item.IsSelected = item == selectedContainer;
+ }
}
}
}