diff --git a/Perspex.Controls/TreeView.cs b/Perspex.Controls/TreeView.cs index c3a9290130..e6331bc7de 100644 --- a/Perspex.Controls/TreeView.cs +++ b/Perspex.Controls/TreeView.cs @@ -6,20 +6,44 @@ namespace Perspex.Controls { - using System.Collections; - using System.Collections.Generic; + using System; using Perspex.Controls.Generators; - using Perspex.Controls.Primitives; using Perspex.Input; + using Perspex.VisualTree; + using System.Collections; + using System.Collections.Generic; + using System.Linq; - public class TreeView : SelectingItemsControl + public class TreeView : ItemsControl { + public static readonly PerspexProperty SelectedItemProperty = + PerspexProperty.Register("SelectedItem", coerce: CoerceSelectedItem); + + static TreeView() + { + SelectedItemProperty.Changed.Subscribe(x => + { + var control = x.Sender as TreeView; + + if (control != null) + { + control.SelectedItemChanged(x.NewValue); + } + }); + } + + public object SelectedItem + { + get { return this.GetValue(SelectedItemProperty); } + set { this.SetValue(SelectedItemProperty, value); } + } + protected override ItemContainerGenerator CreateItemContainerGenerator() { return new TreeItemContainerGenerator(this); } - protected override void MoveSelection(FocusNavigationDirection direction) + protected virtual void MoveSelection(FocusNavigationDirection direction) { // TODO: Up and down movement is a *HACK* and probably pretty slow. Probably needs // rewriting at some point. @@ -70,6 +94,85 @@ namespace Perspex.Controls } } + 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 CoerceSelectedItem(PerspexObject o, object value) + { + //var control = o as SelectingItemsControl; + + //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(); @@ -93,5 +196,25 @@ namespace Perspex.Controls } } } + + private void SelectedItemChanged(object selected) + { + var containers = this.ItemContainerGenerator.GetAll() + .Select(x => x.Item2) + .OfType(); + var selectedContainer = (selected != null) ? + this.ItemContainerGenerator.GetContainerForItem(selected) : + null; + + if (this.Presenter != null && this.Presenter.Panel != null) + { + KeyboardNavigation.SetTabOnceActiveElement(this.Presenter.Panel, selectedContainer); + } + + foreach (var item in containers) + { + item.IsSelected = item == selectedContainer; + } + } } }