internal void HandleGotFocus(TreeViewItemEx container) { if (container != null) { // Initial selection. var selectedItems = SelectedItems; if (selectedItems != null && selectedItems.Count == 0) { MoveSelection(container); } } if (_lastFocusedContainer == container) { return; } if (_lastFocusedContainer != null) { _lastFocusedContainer.IsTabStop = false; } _lastFocusedContainer = container; if (_lastFocusedContainer != null) { _lastFocusedContainer.IsTabStop = true; } IsTabStop = (_lastFocusedContainer == null); }
internal void HandleCollapse(TreeViewItemEx container) { Debug.Assert(container != null); // Unselect all collapsed items. bool childFocused = false; bool childSelected = false; foreach (var childContainer in GetAllContainers(container, true)) { if (childContainer.IsKeyboardFocusWithin) { childFocused = true; } if (childContainer.IsSelected) { childSelected = true; childContainer.IsSelected = false; } } if (childSelected) { MoveSelection(container); } else if (childFocused) { container.FocusWithRetry(); } }
private static TreeViewItemEx GetNextContainer(TreeViewItemEx current, bool onlyVisible) { if (current == null) { return(null); } if (current.HasItems && (!onlyVisible || current.IsExpanded)) { return(current.ItemContainerGenerator.ContainerFromIndex(0) as TreeViewItemEx); } do { var sibling = GetNextSibling(current); if (sibling != null) { return(sibling); } current = current.ParentTreeViewItem; } while (current != null); return(null); }
internal void HandleKeyDown(TreeViewItemEx container, KeyEventArgs e) { // TODO: Consider FlowDirection for Left/Right. switch (e.Key) { case Key.Home: OnNavigationKey(GetFirstContainer(this, true)); e.Handled = true; break; case Key.End: OnNavigationKey(GetLastContainer(this, true)); e.Handled = true; break; case Key.Up: OnNavigationKey(GetPreviousContainer(container ?? GetFocusedContainer(), true)); e.Handled = true; break; case Key.Down: OnNavigationKey(GetNextContainer(container ?? GetFocusedContainer(), true)); e.Handled = true; break; case Key.PageUp: OnNavigationKey(GetPageUpDownContainer(container ?? GetFocusedContainer(), false)); e.Handled = true; break; case Key.PageDown: OnNavigationKey(GetPageUpDownContainer(container ?? GetFocusedContainer(), true)); e.Handled = true; break; case Key.Left: OnNavigationKey((container ?? GetFocusedContainer())?.ParentTreeViewItem); e.Handled = true; break; case Key.A: if (e.KeyboardDevice.Modifiers == ModifierKeys.Control) { SelectAll(); e.Handled = true; } break; case Key.Space: MoveSelection(container ?? GetFocusedContainer()); e.Handled = true; break; } }
private TreeViewItemEx GetPageUpDownContainer(TreeViewItemEx container, bool down) { if (container == null) { return(down ? GetLastContainer(this, true) : GetFirstContainer(this, true)); } double yThreshold = container.TransformToAncestor(this).Transform(new Point()).Y; double itemHeight = container.HeaderHeight; double viewportHeight = _scrollViewer?.ViewportHeight ?? ActualHeight; double offset = viewportHeight - 2 * itemHeight; if (down) { yThreshold += offset; var nextContainer = GetNextContainer(container, true); while (nextContainer != null) { container = nextContainer; double y = container.TransformToAncestor(this).Transform(new Point()).Y; if (y > yThreshold) { break; } nextContainer = GetNextContainer(nextContainer, true); } } else { yThreshold -= offset; var previousContainer = GetPreviousContainer(container, true); while (previousContainer != null) { container = previousContainer; double y = container.TransformToAncestor(this).Transform(new Point()).Y; if (y < yThreshold) { break; } previousContainer = GetPreviousContainer(previousContainer, true); } } return(container); }
private void OnNavigationKey(TreeViewItemEx targetContainer) { if (targetContainer == null) { return; } if (IsControlDown) { targetContainer.FocusWithRetry(); targetContainer.BringIntoView(); } else { MoveSelection(targetContainer); } }
private static TreeViewItemEx GetNextSibling(TreeViewItemEx current) { Debug.Assert(current != null); var itemsControl = current.ParentItemsControl; Debug.Assert(itemsControl != null, "Item container expected to be part of TreeViewEx."); int index = itemsControl.ItemContainerGenerator.IndexFromContainer(current); Debug.Assert(0 <= index && index < itemsControl.Items.Count, "Invalid index."); int nextIndex = index + 1; return((nextIndex < itemsControl.Items.Count) ? itemsControl.ItemContainerGenerator.ContainerFromIndex(nextIndex) as TreeViewItemEx : null); }
private static TreeViewItemEx GetPreviousContainer(TreeViewItemEx current, bool onlyVisible) { if (current == null) { return(null); } var sibling = GetPreviousSibling(current); if (sibling != null) { if (sibling.HasItems && (!onlyVisible || sibling.IsExpanded)) { return(GetLastContainer(sibling, onlyVisible)); } return(sibling); } return(current.ParentTreeViewItem); }
private static List<object> GetRangeItems(ItemsControl itemsControl, TreeViewItemEx first, TreeViewItemEx last, bool onlyVisible) { var containers = GetRangeContainers(itemsControl, first, last, onlyVisible); return containers.Select(c => c.Item).ToList(); }
private static TreeViewItemEx GetPreviousSibling(TreeViewItemEx current) { Debug.Assert(current != null); var itemsControl = current.ParentItemsControl; Debug.Assert(itemsControl != null, "Item container expected to be part of TreeViewEx."); int index = itemsControl.ItemContainerGenerator.IndexFromContainer(current); Debug.Assert(0 <= index && index < itemsControl.Items.Count, "Invalid index."); int previousIndex = index - 1; return (previousIndex >= 0) ? itemsControl.ItemContainerGenerator.ContainerFromIndex(previousIndex) as TreeViewItemEx : null; }
private static List<TreeViewItemEx> GetRangeContainers(ItemsControl itemsControl, TreeViewItemEx first, TreeViewItemEx last, bool onlyVisible) { Debug.Assert(first != null); Debug.Assert(last != null); var list = new List<TreeViewItemEx>(); if (first == last) { list.Add(first); return list; } using (var enumerator = GetAllContainers(itemsControl, onlyVisible).GetEnumerator()) { while (enumerator.MoveNext()) { if (enumerator.Current == first || enumerator.Current == last) { list.Add(enumerator.Current); break; } } while (enumerator.MoveNext()) { list.Add(enumerator.Current); if (enumerator.Current == first || enumerator.Current == last) break; } } Debug.Assert(list.Count > 0); if (list[0] != first) list.Reverse(); Debug.Assert(list[0] == first); Debug.Assert(list[list.Count - 1] == last); return list; }
private static TreeViewItemEx GetNextContainer(TreeViewItemEx current, bool onlyVisible) { if (current == null) return null; if (current.HasItems && (!onlyVisible || current.IsExpanded)) return current.ItemContainerGenerator.ContainerFromIndex(0) as TreeViewItemEx; do { var sibling = GetNextSibling(current); if (sibling != null) return sibling; current = current.ParentTreeViewItem; } while (current != null); return null; }
private static TreeViewItemEx GetPreviousContainer(TreeViewItemEx current, bool onlyVisible) { if (current == null) return null; var sibling = GetPreviousSibling(current); if (sibling != null) { if (sibling.HasItems && (!onlyVisible || sibling.IsExpanded)) return GetLastContainer(sibling, onlyVisible); return sibling; } return current.ParentTreeViewItem; }
internal void HandleKeyDown(TreeViewItemEx container, KeyEventArgs e) { // TODO: Consider FlowDirection for Left/Right. switch (e.Key) { case Key.Home: OnNavigationKey(GetFirstContainer(this, true)); e.Handled = true; break; case Key.End: OnNavigationKey(GetLastContainer(this, true)); e.Handled = true; break; case Key.Up: OnNavigationKey(GetPreviousContainer(container ?? GetFocusedContainer(), true)); e.Handled = true; break; case Key.Down: OnNavigationKey(GetNextContainer(container ?? GetFocusedContainer(), true)); e.Handled = true; break; case Key.PageUp: OnNavigationKey(GetPageUpDownContainer(container ?? GetFocusedContainer(), false)); e.Handled = true; break; case Key.PageDown: OnNavigationKey(GetPageUpDownContainer(container ?? GetFocusedContainer(), true)); e.Handled = true; break; case Key.Left: OnNavigationKey((container ?? GetFocusedContainer())?.ParentTreeViewItem); e.Handled = true; break; case Key.A: if (e.KeyboardDevice.Modifiers == ModifierKeys.Control) { SelectAll(); e.Handled = true; } break; case Key.Space: MoveSelection(container ?? GetFocusedContainer()); e.Handled = true; break; } }
internal void MoveSelection(TreeViewItemEx container) { Debug.Assert(container != null); var selectedItems = SelectedItems; if (selectedItems != null) { var item = container.Item; if (selectedItems.Count == 1 && selectedItems[0] == item) { // Focused moved back to current and only selected item. _shiftSelectionAnchor = container; } else if (IsControlDown) { // Ctrl-click item toggles selection. if (selectedItems.Contains(item)) selectedItems.Remove(item); else selectedItems.Add(item); _shiftSelectionAnchor = container; } else if (IsShiftDown && selectedItems.Count > 0) { // Shift-click extends selection. var anchorContainer = _shiftSelectionAnchor ?? GetContainer(selectedItems[0]); var rangeItems = GetRangeItems(this, anchorContainer, container, true); for (int i = selectedItems.Count - 1; i >= 0; i--) if (!rangeItems.Contains(selectedItems[i])) selectedItems.RemoveAt(i); for (int i = 0; i < rangeItems.Count; i++) if (!selectedItems.Contains(rangeItems[i])) selectedItems.Add(rangeItems[i]); } else { // Single selection. for (int i = selectedItems.Count - 1; i >= 0; i--) if (selectedItems[i] != item) selectedItems.RemoveAt(i); if (!selectedItems.Contains(item)) selectedItems.Add(item); _shiftSelectionAnchor = container; } } container.FocusWithRetry(); container.BringIntoView(); }
internal void HandleGotFocus(TreeViewItemEx container) { if (container != null) { // Initial selection. var selectedItems = SelectedItems; if (selectedItems != null && selectedItems.Count == 0) MoveSelection(container); } if (_lastFocusedContainer == container) return; if (_lastFocusedContainer != null) _lastFocusedContainer.IsTabStop = false; _lastFocusedContainer = container; if (_lastFocusedContainer != null) _lastFocusedContainer.IsTabStop = true; IsTabStop = (_lastFocusedContainer == null); }
private static List <TreeViewItemEx> GetRangeContainers(ItemsControl itemsControl, TreeViewItemEx first, TreeViewItemEx last, bool onlyVisible) { Debug.Assert(first != null); Debug.Assert(last != null); var list = new List <TreeViewItemEx>(); if (first == last) { list.Add(first); return(list); } using (var enumerator = GetAllContainers(itemsControl, onlyVisible).GetEnumerator()) { while (enumerator.MoveNext()) { if (enumerator.Current == first || enumerator.Current == last) { list.Add(enumerator.Current); break; } } while (enumerator.MoveNext()) { list.Add(enumerator.Current); if (enumerator.Current == first || enumerator.Current == last) { break; } } } Debug.Assert(list.Count > 0); if (list[0] != first) { list.Reverse(); } Debug.Assert(list[0] == first); Debug.Assert(list[list.Count - 1] == last); return(list); }
private TreeViewItemEx GetPageUpDownContainer(TreeViewItemEx container, bool down) { if (container == null) return down ? GetLastContainer(this, true) : GetFirstContainer(this, true); double yThreshold = container.TransformToAncestor(this).Transform(new Point()).Y; double itemHeight = container.HeaderHeight; double viewportHeight = _scrollViewer?.ViewportHeight ?? ActualHeight; double offset = viewportHeight - 2 * itemHeight; if (down) { yThreshold += offset; var nextContainer = GetNextContainer(container, true); while (nextContainer != null) { container = nextContainer; double y = container.TransformToAncestor(this).Transform(new Point()).Y; if (y > yThreshold) break; nextContainer = GetNextContainer(nextContainer, true); } } else { yThreshold -= offset; var previousContainer = GetPreviousContainer(container, true); while (previousContainer != null) { container = previousContainer; double y = container.TransformToAncestor(this).Transform(new Point()).Y; if (y < yThreshold) break; previousContainer = GetPreviousContainer(previousContainer, true); } } return container; }
private static List <object> GetRangeItems(ItemsControl itemsControl, TreeViewItemEx first, TreeViewItemEx last, bool onlyVisible) { var containers = GetRangeContainers(itemsControl, first, last, onlyVisible); return(containers.Select(c => c.Item).ToList()); }
internal void MoveSelection(TreeViewItemEx container) { Debug.Assert(container != null); var selectedItems = SelectedItems; if (selectedItems != null) { var item = container.Item; if (selectedItems.Count == 1 && selectedItems[0] == item) { // Focused moved back to current and only selected item. _shiftSelectionAnchor = container; } else if (IsControlDown) { // Ctrl-click item toggles selection. if (selectedItems.Contains(item)) { selectedItems.Remove(item); } else { selectedItems.Add(item); } _shiftSelectionAnchor = container; } else if (IsShiftDown && selectedItems.Count > 0) { // Shift-click extends selection. var anchorContainer = _shiftSelectionAnchor ?? GetContainer(selectedItems[0]); var rangeItems = GetRangeItems(this, anchorContainer, container, true); for (int i = selectedItems.Count - 1; i >= 0; i--) { if (!rangeItems.Contains(selectedItems[i])) { selectedItems.RemoveAt(i); } } for (int i = 0; i < rangeItems.Count; i++) { if (!selectedItems.Contains(rangeItems[i])) { selectedItems.Add(rangeItems[i]); } } } else { // Single selection. for (int i = selectedItems.Count - 1; i >= 0; i--) { if (selectedItems[i] != item) { selectedItems.RemoveAt(i); } } if (!selectedItems.Contains(item)) { selectedItems.Add(item); } _shiftSelectionAnchor = container; } } container.FocusWithRetry(); container.BringIntoView(); }
private void OnNavigationKey(TreeViewItemEx targetContainer) { if (targetContainer == null) return; if (IsControlDown) { targetContainer.FocusWithRetry(); targetContainer.BringIntoView(); } else { MoveSelection(targetContainer); } }
internal void HandleCollapse(TreeViewItemEx container) { Debug.Assert(container != null); // Unselect all collapsed items. bool childFocused = false; bool childSelected = false; foreach (var childContainer in GetAllContainers(container, true)) { if (childContainer.IsKeyboardFocusWithin) { childFocused = true; } if (childContainer.IsSelected) { childSelected = true; childContainer.IsSelected = false; } } if (childSelected) { MoveSelection(container); } else if (childFocused) { container.FocusWithRetry(); } }