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; + } } } }