Пример #1
0
        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);
        }
Пример #2
0
        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();
            }
        }
Пример #3
0
        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);
        }
Пример #4
0
        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;
            }
        }
Пример #5
0
        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);
        }
Пример #6
0
        private void OnNavigationKey(TreeViewItemEx targetContainer)
        {
            if (targetContainer == null)
            {
                return;
            }

            if (IsControlDown)
            {
                targetContainer.FocusWithRetry();
                targetContainer.BringIntoView();
            }
            else
            {
                MoveSelection(targetContainer);
            }
        }
Пример #7
0
        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);
        }
Пример #8
0
        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);
        }
Пример #9
0
 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();
 }
Пример #10
0
        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;
        }
Пример #11
0
        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;
        }
Пример #12
0
        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;
        }
Пример #13
0
        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;
        }
Пример #14
0
        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;
            }
        }
Пример #15
0
        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();
        }
Пример #16
0
        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);
        }
Пример #17
0
        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);
        }
Пример #18
0
        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;
        }
Пример #19
0
        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());
        }
Пример #20
0
        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();
        }
Пример #21
0
        private void OnNavigationKey(TreeViewItemEx targetContainer)
        {
            if (targetContainer == null)
                return;

            if (IsControlDown)
            {
                targetContainer.FocusWithRetry();
                targetContainer.BringIntoView();
            }
            else
            {
                MoveSelection(targetContainer);
            }
        }
Пример #22
0
        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();
            }
        }