// ----------------------------------------------------------------------- // // Copyright 2014 MIT Licence. See licence.md for more information. // // ----------------------------------------------------------------------- namespace Perspex.Controls.Primitives { using System; using System.Collections; using System.Linq; using Perspex.Input; using Perspex.VisualTree; public class SelectingItemsControl : ItemsControl { public static readonly PerspexProperty SelectedItemProperty = PerspexProperty.Register("SelectedItem"); static SelectingItemsControl() { FocusableProperty.OverrideDefaultValue(typeof(SelectingItemsControl), true); SelectedItemProperty.Changed.Subscribe(x => { var control = x.Sender as SelectingItemsControl; if (control != null) { control.SelectedItemChanged(x.NewValue); } }); } public object SelectedItem { get { return this.GetValue(SelectedItemProperty); } set { this.SetValue(SelectedItemProperty, value); } } protected static int GetIndexOfItem(IEnumerable items, object item) { if (items != null) { int index = 0; foreach (var i in items) { if (object.ReferenceEquals(i, item)) { return index; } ++index; } } return -1; } protected int GetIndexOfItem(object item) { return GetIndexOfItem(this.Items, item); } protected virtual void MoveSelection(FocusNavigationDirection direction) { if (this.SelectedItem != null) { int offset = 0; switch (direction) { case FocusNavigationDirection.Up: offset = -1; break; case FocusNavigationDirection.Down: offset = 1; break; } if (offset != 0) { var currentIndex = GetIndexOfItem(this.SelectedItem); var index = currentIndex + offset; if (index >= 0 && index < this.Items.Cast().Count()) { this.SelectedItem = this.Items.Cast().ElementAt(index); } } } } protected override void OnKeyDown(KeyEventArgs e) { 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; } 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; } } 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; foreach (var item in containers) { item.IsSelected = item == selectedContainer; } } } }