Esempio n. 1
0
        /// <summary>
        /// 在结点被收缩起来时,应该它的子结点的所有数据在_objectItems中对应的项都移除。
        /// </summary>
        /// <param name="treeNode"></param>
        private void OnNodeCollapsed(TreeGridRow treeNode)
        {
            //处理 LazyLoading

            //结点被折叠后事件。
            //如果懒加载开启后,则在折叠时清空所有子结点。

            //不处理根结点。
            if (treeNode != this.RootNode)
            {
                //更新布局
                var itemKey = GetId(treeNode.DataContext);
                _renderExpansion.Remove(itemKey);

                if (this.IsLazyLoading && this.ClearCollapsedNodes && treeNode.Items.Count > 0)
                {
                    //deregisters listeners for all ancestors
                    if (this.ObserveChildItems)
                    {
                        _monitor.RemoveNodes(treeNode.Items);
                    }

                    treeNode.ItemsSource = null;
                    TreeGridHelper.CreateDummyItem(treeNode);

                    //TODO do we have collapsed event if all childs are being filtered?
                    //if yes, we need to set the dummy nodes visibility depending
                    //on the filtered childs (visible if at least 1 visible child)
                }
            }
        }
Esempio n. 2
0
        private static void TreeGridRow_Collapsed(object sender, RoutedEventArgs e)
        {
            var row = e.OriginalSource as TreeGridRow;

            if (!TreeGridHelper.IsDummyItem(row))
            {
                (sender as TreeGrid).OnNodeCollapsed(row);
            }
        }
Esempio n. 3
0
        private static void PropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var sender = (TreeGridHeaderRowPresenter)d;

            if (e.Property == ColumnHeaderTemplateProperty || e.Property == ColumnHeaderTemplateSelectorProperty)
            {
                TreeGridHelper.CheckTemplateAndTemplateSelector("TreeGridHeaderRowPresenter", ColumnHeaderTemplateProperty, ColumnHeaderTemplateSelectorProperty, sender);
            }
            sender.UpdateAllHeaders(e.Property);
        }
Esempio n. 4
0
        protected override void OnPreviewKeyDown(KeyEventArgs e)
        {
            base.OnPreviewKeyDown(e);

            //在编辑控件按 Tab 切换到下一列
            if (e.Key == Key.Tab)
            {
                bool moveNext = !TreeGridHelper.IsShiftPressed();
                this.Column.EditNextColumnOnTabKey(this, moveNext, e, this.Column);
            }
        }
Esempio n. 5
0
        /// <summary>
        /// 在列的项变化时,同步变化对应的单元格列表 UIChildren。
        /// </summary>
        /// <param name="e"></param>
        private void OnColumnCollectionChanged(TreeGridColumnCollectionChangedEventArgs e)
        {
            TreeGridHelper.UpdateDesiredWidthListOnColumnChanged(ref this._desiredWidthList, e);

            if (this.TryConnect())
            {
                this._cellsPresenter.UpdateItemsSourceOnColumnsChanged(e);

                base.InvalidateMeasure();
            }
        }
Esempio n. 6
0
        /// <summary>
        /// 折叠起那些不是当前选择行或其父节点的所有行。
        /// </summary>
        private void ApplyAutoCollapse()
        {
            if (!this.AutoCollapse)
            {
                return;
            }

            object selected     = this.SelectedItem;
            var    itemsControl = this.RootItemsControl;

            if (selected == null)
            {
                //if we don't have a selected item, just collapse the
                //root items
                foreach (TreeGridRow node in TreeGridHelper.TraverseRows(itemsControl))
                {
                    node.IsExpanded = false;
                }
            }
            else
            {
                var parents = this.GetParentItemList(selected);
                foreach (object parent in parents)
                {
                    var parentNode = this.FindChildRow(parent, itemsControl);
                    if (parentNode == null)
                    {
                        string msg = "Cannot collapse item '{0}' - the item does not exist in the hierarchy of the tree's bound items.";
                        msg = String.Format(msg, GetId(parent));
                        throw new InvalidOperationException(msg);
                    }

                    foreach (TreeGridRow item in TreeGridHelper.TraverseRows(itemsControl))
                    {
                        //collapse all items that are no ancestors
                        if (item == parentNode)
                        {
                            continue;
                        }
                        item.IsExpanded = false;
                    }

                    //go a level deeper
                    itemsControl = parentNode;
                }

                //finally collapse the item and its siblings
                foreach (TreeGridRow item in TreeGridHelper.TraverseRows(itemsControl))
                {
                    item.IsExpanded = false;
                }
            }
        }
Esempio n. 7
0
        /// <summary>
        /// 选择核心逻辑。
        ///
        /// 处理多选及单选状态下的 SelectionModel 中数据状态。
        /// </summary>
        /// <param name="oldItem"></param>
        /// <param name="newItem"></param>
        private void SelectionCore(object oldItem, object newItem)
        {
            var ctrlPressed  = TreeGridHelper.IsCtrlPressed();
            var shiftPressed = TreeGridHelper.IsShiftPressed();

            //当前是否正处于多选模式下。
            var inMultiSelectionMode = this._forceMultiSelect || ctrlPressed || shiftPressed;

            this.ShiftSelectStart(shiftPressed, oldItem, newItem);

            //如果不是多选状态,则先清空选中行状态。
            var sm = this.SelectionModel;

            if (!inMultiSelectionMode)
            {
                sm.ClearSelectedItems();
            }

            if (newItem != null)
            {
                if (ctrlPressed || this._forceMultiSelect)
                {
                    //反选该行
                    var selected = sm.InnerItems.Contains(newItem);
                    sm.MarkItemSelected(newItem, !selected);
                }
                else if (shiftPressed)
                {
                    sm.ClearSelectedItems();

                    if (this._shiftStartItem != null)
                    {
                        this.ShiftSelectEnd(newItem);
                    }
                }
                else
                {
                    sm.MarkItemSelected(newItem, true);
                }
            }
            else
            {
                if (!this._forceMultiSelect)
                {
                    sm.ClearSelectedItems();
                }
            }
        }
Esempio n. 8
0
        /// <summary>
        /// 让当前所有行的单元格重新测量。
        /// </summary>
        private void InvalidateCells()
        {
            var grid = this.TreeGrid;

            if (grid != null && grid.IsColumnsVirtualizingEnabled)
            {
                var rows = TreeGridHelper.TraverseRows(grid);
                foreach (var item in rows)
                {
                    if (item.CellsPanel != null)
                    {
                        item.CellsPanel.InvalidateMeasure();
                    }
                }
            }
        }
Esempio n. 9
0
        /// <summary>
        /// Updates the tree with newly added items.
        /// </summary>
        /// <param name="observed">The observed collection.</param>
        /// <param name="e">Collection event args.</param>
        public void HandleNewChildItems(ICollection observed, NotifyCollectionChangedEventArgs e)
        {
            IList childs = e.NewItems;

            if (childs.Count == 0)
            {
                return;
            }

            //get the node of the parent item that contains the evented childs
            var parentNode = GetParentNode(childs[0], observed);

            if (parentNode == null)
            {
                return;
            }

            //if the node is expanded or does not load lazily, or
            //already contains valid items, create nodes
            if (parentNode.IsExpanded || !tree.IsLazyLoading || !TreeGridHelper.ContainsDummyNode(parentNode))
            {
                var rawLayout = tree._renderExpansion;
                try
                {
                    tree._renderExpansion = null;

                    parentNode.ItemsSource = childs;
                }
                finally
                {
                    tree._renderExpansion = rawLayout;
                }

                //refresh the node in order to apply sorting (or any other
                //features that will be incorporated)
                parentNode.Items.Refresh();
            }
            else if (parentNode.Items.Count == 0)
            {
                //if the tree is in lazy loading mode and the item did
                //not contain any childs before, we have to add a dummy
                //node to render a expander
                parentNode.Items.Add(TreeGridHelper.CreateDummyItem());
            }
        }
Esempio n. 10
0
        private void OnNodeExpanded(TreeGridRow treeNode)
        {
            //处理 LazyLoading
            //结点被展开后事件
            //完成懒加载时的结点创建工作,并设置各结点的 Filter 属性。

            object item = treeNode.DataContext;

            if (item != null)
            {
                //布局
                var itemKey = GetId(item);
                _renderExpansion.Add(itemKey);

                var nodeItems = treeNode.Items;

                //懒加载状态下,创建结点。
                if (this.IsLazyLoading)
                {
                    TreeGridHelper.ClearDummyChildNode(treeNode);

                    if (nodeItems.Count == 0)
                    {
                        var childItems = this.GetChildItems(item);

                        treeNode.ItemsSource = childItems;

                        //刷新以排序
                        if (nodeItems.NeedsRefresh)
                        {
                            nodeItems.Refresh();
                        }
                    }
                }

                if (nodeItems.Count == 0)
                {
                    //如果结点没有数据,则不需要展开它。
                    treeNode.IsExpanded = false;
                    _renderExpansion.Remove(itemKey);
                }
            }
        }
Esempio n. 11
0
        /// <summary>
        /// Updates the tree if items were removed from an observed
        /// child collection. This might cause rendered tree nodes
        /// to be removed. In case lazy loading is enabled, the update
        /// of the UI may be as subtle as to remove an expander from
        /// a collapsed node if the represented item's childs were
        /// removed (or the childs that pass an active filter).<br/>
        /// </summary>
        /// <param name="observed">The observed collection.</param>
        /// <param name="e">The event arguments that provide the
        /// removed items.</param>
        private void HandleRemovedChildItems(ICollection observed, NotifyCollectionChangedEventArgs e)
        {
            IList childs = e.OldItems;

            if (childs.Count == 0)
            {
                return;
            }

            //get the node of the parent item that contains the evented childs
            var parentNode = GetParentNode((object)childs[0], observed);

            if (parentNode == null)
            {
                return;
            }

            foreach (object childItem in childs)
            {
                //check if we have a corresponding open node
                //-> not necessarily the case if we're doing lazy loading
                var childRow = tree.FindChildRow(childItem, parentNode);
                if (childRow != null)
                {
                    //unregister listeners
                    UnregisterListeners(childRow);
                    //remove node from UI
                    parentNode.Items.Remove(childRow);
                }
            }

            //in case of lazy loading, the tree might contain a dummy node
            //(has not been expanded). However, it might be that it's now
            //completely empty...
            if (observed.Count == 0)
            {
                TreeGridHelper.ClearDummyChildNode(parentNode);
                parentNode.IsExpanded = false;
            }
        }
Esempio n. 12
0
        /// <summary>
        /// 测量所有已经生成的单元格。
        /// </summary>
        /// <param name="columns"></param>
        /// <param name="availableSize"></param>
        /// <returns></returns>
        private Size MeasureChild(TreeGridColumnCollection columns, Size availableSize)
        {
            double maxWidth         = availableSize.Width;
            double maxHeight        = availableSize.Height;
            double rowDesiredHeight = 0.0;                 //行最终需要的高度
            double rowDesiredWidth  = 0.0;                 //行最终需要的宽度
            bool   firstTime        = true;                //是否在 Init 状态下还没有初始化过 DesiredWidthList。
            var    cells            = this.InternalChildren;

            for (int i = this._from, j = 0; i <= this._to; i++, j++)
            {
                var column = columns[i];

                //当前行还可用的宽度
                double rowAvaiableWidth = Math.Max(0, maxWidth - rowDesiredWidth);

                //第一列额外元素需要的宽度
                double headersDesiredWidth = 0;

                #region 测量第一列额外元素需要的宽度

                if (i == 0)
                {
                    //测量 RowHeader
                    if (this.ShowRowHeader)
                    {
                        headersDesiredWidth += this.RowHeaderWidth;
                        rowAvaiableWidth    -= this.RowHeaderWidth;
                        //this._rowHeaderContainer.Measure(new Size(columnWidth, maxHeight));
                        //x += this._rowHeaderContainer.DesiredSize.Width;
                        //columnWidth -= this._rowHeaderContainer.DesiredSize.Width;
                    }

                    //留下 FirstColumnIndent
                    var firstColumnIndent = Math.Min(this.FirstColumnIndent, rowAvaiableWidth);
                    headersDesiredWidth += firstColumnIndent;
                    rowAvaiableWidth    -= firstColumnIndent;

                    //测量 Expander
                    if (this.ShowExpander)
                    {
                        var expander = this.Expander;
                        expander.Measure(new Size(rowAvaiableWidth, maxHeight));
                        headersDesiredWidth += expander.DesiredSize.Width;
                        rowAvaiableWidth    -= expander.DesiredSize.Width;
                    }
                }

                #endregion

                var cell = cells[j];

                //测量单元格
                var state = column.State;
                if (state == ColumnMeasureState.Init || state == ColumnMeasureState.Headered)
                {
                    if (firstTime)
                    {
                        TreeGridHelper.EnsureDesiredWidthList(ref this._desiredWidthList, this._treeGrid.Columns);
                        this.LayoutUpdated += this.OnMeasureLayoutUpdated;
                        firstTime           = false;
                    }

                    cell.Measure(new Size(rowAvaiableWidth, maxHeight));

                    //只有在虚拟化后的当前页面时,才影响动态宽度。
                    if (this._cellsPresenter.IsOnCurrentPage)
                    {
                        //当前列需要的宽度应该是列的宽度加额外元素的宽度。
                        column.EnsureDataWidth(cell.DesiredSize.Width + headersDesiredWidth);
                    }
                    this._desiredWidthList[column.StableIndex] = column.DesiredDataWidth;

                    rowDesiredWidth += column.DesiredDataWidth;
                }
                else
                {
                    var actualWidth = column.CalculateActualWidth();

                    rowAvaiableWidth = Math.Min(rowAvaiableWidth, actualWidth - headersDesiredWidth);

                    cell.Measure(new Size(rowAvaiableWidth, maxHeight));

                    rowDesiredWidth += actualWidth;
                }

                rowDesiredHeight = Math.Max(rowDesiredHeight, cell.DesiredSize.Height);
            }

            rowDesiredWidth += TreeGridHeaderRowPresenter.c_EndPadding;

            this._cellsPresenter.IsOnCurrentPageValid = false;

            return(new Size(rowDesiredWidth, rowDesiredHeight));
        }
Esempio n. 13
0
 private void OnColumnHeaderTemplateSelectorChanged(DependencyPropertyChangedEventArgs e)
 {
     TreeGridHelper.CheckTemplateAndTemplateSelector("GridViewColumnHeader", GridView.ColumnHeaderTemplateProperty, GridView.ColumnHeaderTemplateSelectorProperty, this);
 }
Esempio n. 14
0
 /// <summary>
 /// 保证 _desiredWidthList 与 columns 长度一致。
 /// </summary>
 internal void EnsureDesiredWidthList()
 {
     TreeGridHelper.EnsureDesiredWidthList(ref this._desiredWidthList, this.Columns);
 }
Esempio n. 15
0
 /// <summary>
 /// 当前 Columns 集合发生变更时,执行此回调。
 /// </summary>
 /// <param name="e"></param>
 internal virtual void OnColumnCollectionChanged(TreeGridColumnCollectionChangedEventArgs e)
 {
     TreeGridHelper.UpdateDesiredWidthListOnColumnChanged(ref this._desiredWidthList, e);
 }
Esempio n. 16
0
 private void OnHeaderTemplateSelectorChanged(DependencyPropertyChangedEventArgs e)
 {
     TreeGridHelper.CheckTemplateAndTemplateSelector("Header", HeaderTemplateProperty, HeaderTemplateSelectorProperty, this);
     this.OnPropertyChanged(TreeGridColumn.HeaderTemplateSelectorProperty.Name);
 }