Exemplo n.º 1
0
        /// <summary>
        /// Expands a node recursively till all child/grandchild nodes are expanded.
        /// All its parent nodes up to root must already be expanded.
        /// Otherwise there is no effect.
        /// </summary>
        /// <param name="data">The data object that the target node contains</param>
        public void ExpandItemRecursive(object data)
        {
            int index;
            TreeGridViewItemInfo itemInfo = this.FindItemInfoForData(data, out index);

            ExpandItemRecursiveInternal(itemInfo, index);
        }
Exemplo n.º 2
0
        /// <summary>
        /// Collapse a node containing the given data.
        /// All its parent nodes up to root must already be expanded, including itself.
        /// Otherwise there is no effect.
        /// </summary>
        /// <param name="data">The data object that the target node contains</param>
        public void CollapseItem(object data)
        {
            // Collapse a node is a simple operation as to remove any following nodes whose level
            // is bigger than this one, until a node with equal or smaller level value is reached.
            // in the process if a removed node was expanded, we keep it in orphanExpandedItemsStore
            int index;
            TreeGridViewItemInfo itemInfo = this.FindItemInfoForData(data, out index);
            bool focusRemoved             = false;

            if (itemInfo != null && itemInfo.IsExpanded)
            {
                int n     = index + 1;
                int count = 0;
                while (n < this.itemInfoFlatList.Count)
                {
                    var childInfo = this.itemInfoFlatList[n];
                    n++;
                    if (childInfo.Level > itemInfo.Level)
                    {
                        count++;
                        // before remove it, check if its selected or focused on
                        if (base.SelectedItem == childInfo)
                        {
                            // selected item is removed, select the parent item instead
                            base.SelectedItem = itemInfo;
                        }

                        if (this.focusItemInfo == childInfo)
                        {
                            this.focusItemInfo = null;
                            focusRemoved       = true;
                        }

                        if (childInfo.IsExpanded)
                        {
                            this.orphanExpandedItemsStore.Add(childInfo.Data);
                        }
                    }
                    else
                    {
                        // equal or smaller Level value reached, no more child nodes
                        break;
                    }
                }
                if (count > 0)
                {
                    itemInfo.IsExpanded = false;
                    if (focusRemoved)
                    {
                        this.restoreFocusItemInfo = itemInfo;
                    }
                    else
                    {
                        this.restoreFocusItemInfo = this.focusItemInfo;
                    }
                    this.itemInfoFlatList.RemoveRange(index + 1, count);
                }
            }
        }
Exemplo n.º 3
0
        /// <summary>
        /// Clean up the item container
        /// </summary>
        /// <param name="element">The TreeGridViewItem to be discarded</param>
        /// <param name="item">The associated data object (TreeGridViewItemInfo)</param>
        protected override void ClearContainerForItemOverride(DependencyObject element, object item)
        {
            TreeGridViewItemInfo info = item as TreeGridViewItemInfo;
            TreeGridViewItem     tgvi = element as TreeGridViewItem;

            tgvi.ParentView = null;
            base.ClearContainerForItemOverride(element, item);
        }
Exemplo n.º 4
0
        public void ScrollItemIntoView(object data)
        {
            int index;

            // Consider optimizing this for large lists...
            TreeGridViewItemInfo info = this.FindItemInfoForData(data, out index);

            if (info != null)
            {
                this.ScrollIntoView(info);
            }
        }
Exemplo n.º 5
0
 void ExpandFully()
 {
     if (this.ParentView != null)
     {
         TreeGridViewItemInfo info = this.DataContext as TreeGridViewItemInfo;
         if (info != null)
         {
             this.ParentView.ExpandItemRecursive(info.Data);
             this.IsExpanded = true;
         }
     }
 }
Exemplo n.º 6
0
        void ExpandItemRecursiveInternal(TreeGridViewItemInfo itemInfo, int index)
        {
            // Expand a node recursively till the whole subtree under it are expanded
            // this occurs when user press '*' on a node
            // handling should be careful since the subtree may already be partially expanded
            int partialExpandedCount = 0;

            if (itemInfo != null)
            {
                var itemsToInsert = new List <TreeGridViewItemInfo>();
                if (!itemInfo.IsExpanded)
                {
                    this.GetChildItemInfoRecursive(itemInfo, itemsToInsert);
                    partialExpandedCount = 0;
                }
                else
                {
                    int x = index + 1;
                    while (x < this.itemInfoFlatList.Count)
                    {
                        var childInfo = this.itemInfoFlatList[x];
                        x++;
                        if (childInfo.Level > itemInfo.Level)
                        {
                            partialExpandedCount++;
                            itemsToInsert.Add(childInfo);
                            if (!childInfo.IsExpanded)
                            {
                                this.GetChildItemInfoRecursive(childInfo, itemsToInsert);
                            }
                        }
                        else
                        {
                            break;
                        }
                    }
                }

                if (partialExpandedCount < itemsToInsert.Count)
                {
                    // save focus
                    this.restoreFocusItemInfo = this.focusItemInfo;
                    // first collapse the item (in case it is partially expanded already)
                    if (partialExpandedCount > 0)
                    {
                        this.itemInfoFlatList.RemoveRange(index + 1, partialExpandedCount);
                    }
                    // insert the whole sub tree
                    this.itemInfoFlatList.InsertRange(index + 1, itemsToInsert);
                }
            }
        }
Exemplo n.º 7
0
        // find parent item of specified item;
        // look back to find the first item whose Level value is smaller than this one
        private TreeGridViewItemInfo GetParentItemInfo(TreeGridViewItemInfo childInfo)
        {
            int childIndex = this.itemInfoFlatList.IndexOf(childInfo);

            if (childIndex >= 0 && childIndex < this.itemInfoFlatList.Count)
            {
                for (int i = childIndex - 1; i >= 0; i--)
                {
                    var parentInfo = this.itemInfoFlatList[i];
                    if (parentInfo.Level < childInfo.Level)
                    {
                        return(parentInfo);
                    }
                }
            }
            return(null);
        }
Exemplo n.º 8
0
        /// <summary>
        /// Prepare the item container.
        /// This is after ItemContainerGenerator created a TreeGridViewItem, and we have a chance to
        /// do some intialization work
        /// </summary>
        /// <param name="element">The TreeGridViewItem that is newly created (or recycled)</param>
        /// <param name="item">The data object associated (a TreeGridViewItemInfo object)</param>
        protected override void PrepareContainerForItemOverride(DependencyObject element, object item)
        {
            TreeGridViewItemInfo info      = item as TreeGridViewItemInfo;
            TreeGridViewItem     container = element as TreeGridViewItem;

            if (info != null)
            {
                container.ParentView = this;

                // initialize necessary properties
                container.Level      = info.Level;
                container.IsExpanded = info.IsExpanded;

                container.HasChildren = this.DataHasChildren(info.Data);
                base.PrepareContainerForItemOverride(element, info.Data);
            }
        }
Exemplo n.º 9
0
        private void GetChildAndOrphanItemInfo(TreeGridViewItemInfo itemInfo, List <TreeGridViewItemInfo> appendList)
        {
            List <TreeGridViewItemInfo> childrenInfo = this.CreateChildItemInfoCollection(itemInfo);

            if (childrenInfo != null && childrenInfo.Count > 0)
            {
                itemInfo.IsExpanded = true;
                foreach (var c in childrenInfo)
                {
                    appendList.Add(c);
                    if (this.orphanExpandedItemsStore.Contains(c.Data))
                    {
                        this.orphanExpandedItemsStore.Remove(c.Data);
                        this.GetChildAndOrphanItemInfo(c, appendList);
                    }
                }
            }
        }
Exemplo n.º 10
0
 private void ItemContainerGenerator_StatusChanged(object sender, EventArgs e)
 {
     if (this.ItemContainerGenerator.Status == System.Windows.Controls.Primitives.GeneratorStatus.ContainersGenerated)
     {
         if (this.restoreFocusItemInfo != null)
         {
             TreeGridViewItem tgvi = this.ItemContainerGenerator.ContainerFromItem(this.restoreFocusItemInfo) as TreeGridViewItem;
             if (tgvi != null)
             {
                 if (this.IsFocused)
                 {
                     tgvi.Focus();
                     this.restoreFocusItemInfo = null;
                 }
             }
         }
     }
 }
Exemplo n.º 11
0
        /// <summary>
        /// Move focus to parent item
        /// </summary>
        /// <param name="childItem">The currently focused item</param>
        /// <returns>true if succeeds; otherwise false</returns>
        internal bool FocusToParentItem(TreeGridViewItem childItem)
        {
            TreeGridViewItemInfo childInfo = this.ItemContainerGenerator.ItemFromContainer(childItem) as TreeGridViewItemInfo;

            if (childInfo != null)
            {
                var parentInfo = this.GetParentItemInfo(childInfo);
                if (parentInfo != null)
                {
                    this.ScrollIntoView(parentInfo);
                    TreeGridViewItem parentContainer = this.ItemContainerGenerator.ContainerFromItem(parentInfo) as TreeGridViewItem;
                    if (parentContainer != null)
                    {
                        return(parentContainer.Focus());
                    }
                }
            }
            return(false);
        }
Exemplo n.º 12
0
        /// <summary>
        /// Expands a node containing the given data.
        /// All its parent/grandparent nodes up to root must already be expanded.
        /// Otherwise there is no effect.
        /// </summary>
        /// <param name="data">The data object that the target node contains</param>
        /// <returns>true if the item is already expanded, or the expand succeeds</returns>
        public bool ExpandItem(object data)
        {
            /*
             * additionally handles a special scenario:
             * Assume a tree like this (-> denotes parent-child relationship):
             * A(expanded) -> B(expanded) -> C
             *
             * now user collapse A, all child/grandchild nodes (including B and C) are removed from the flat list;
             * later user expands A again, B is created (but default collapsed) and
             * inserted after A into the list, but user expects B to be expanded as it was.
             * So we need to furthur expand B as well.
             * orphanExpandedItems is used to remember nodes like B (expanded before removed),
             * whenever an item is expanded, we'll check in to orphanExpandedItems to see if any
             * of the child items need further expansion, and so on.
             * (as a matter of fact WPF TreeView internally does similar things.)
             */

            int index;
            TreeGridViewItemInfo itemInfo = this.FindItemInfoForData(data, out index);

            if (itemInfo == null)
            {
                return(false);
            }

            if (itemInfo.IsExpanded)
            {
                return(true);
            }

            var itemsToInsert = new List <TreeGridViewItemInfo>();

            this.GetChildAndOrphanItemInfo(itemInfo, itemsToInsert);

            if (itemsToInsert.Count > 0)
            {
                // save focus and restore later
                this.restoreFocusItemInfo = this.focusItemInfo;
                this.itemInfoFlatList.InsertRange(index + 1, itemsToInsert);
            }

            return(true);
        }
Exemplo n.º 13
0
        /// <summary>
        /// Select/unselect a node.
        /// All parent nodes up to root must already be expanded.
        /// Otherwise there is no effect.
        /// </summary>
        /// <param name="data">The data that the target node contains</param>
        /// <param name="selected">true: select the node; false: unselect the node</param>
        public void SelectItem(object data, bool selected)
        {
            int index;
            TreeGridViewItemInfo info = this.FindItemInfoForData(data, out index);

            if (info != null)
            {
                this.ScrollIntoView(info);

                this.Dispatcher.BeginInvoke(
                    (Action)(() =>
                {
                    TreeGridViewItem container = this.ItemContainerGenerator.ContainerFromIndex(index) as TreeGridViewItem;
                    if (container != null)
                    {
                        container.IsSelected = selected;
                    }
                }),
                    System.Windows.Threading.DispatcherPriority.Background);
            }
        }
Exemplo n.º 14
0
        // Get children items of an item;
        // The binding path is expected from TreeGridView.ItemsTemplate which should be a HierarchicalDataTemplate,
        // Use reflection to get the property value
        private List <TreeGridViewItemInfo> CreateChildItemInfoCollection(TreeGridViewItemInfo info)
        {
            List <TreeGridViewItemInfo> result = null;

            if (info == null || info.Data == null)
            {
                return(result);
            }
            IEnumerable childCollection = this.GetChildCollection(info.Data);

            if (childCollection != null)
            {
                foreach (var c in childCollection)
                {
                    if (result == null)
                    {
                        result = new List <TreeGridViewItemInfo>();
                    }
                    result.Add(new TreeGridViewItemInfo(c, info.Level + 1));
                }
            }

            return(result);
        }
Exemplo n.º 15
0
 /// <summary>
 /// Called by an item to notify the view when it gets focus
 /// The view has to know the currently focused item
 /// </summary>
 /// <param name="childItem">the child item got focus</param>
 internal void NotifyItemGotFocus(TreeGridViewItem childItem)
 {
     this.focusItemInfo = this.ItemContainerGenerator.ItemFromContainer(childItem) as TreeGridViewItemInfo;
     // clear the pending focus restore since a new focus is set by user
     this.restoreFocusItemInfo = null;
 }