Пример #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)
                }
            }
        }
Пример #2
0
        /// <summary>
        /// 为指定的结点应用 <see cref="RowStyle"/> 样式。
        ///
        /// 子类重写此方法用于应用自定义样式。
        /// </summary>
        /// <param name="treeNode">The node to be styled.</param>
        private void ApplyNodeStyle(TreeGridRow treeNode)
        {
            var style = this.RowStyle;

            if (style != null)
            {
                treeNode.Style = style;
            }
        }
Пример #3
0
 //DummyItem 意思是展开树节点时,显示子节点正在加载中的一个临时树节点。
 /// <summary>
 /// Checks whether a given tree node contains a dummy node to
 /// ensure it's rendered with an expander, and removes the node.
 /// </summary>
 /// <param name="treeNode">The node to be checked for dummy
 /// child nodes.</param>
 internal static void ClearDummyChildNode(TreeGridRow treeNode)
 {
     ////if the item has never been expanded yet, it contains a dummy
     ////node - replace that one and insert real data
     //if (ContainsDummyNode(treeNode))
     //{
     //    treeNode.Items.Clear();
     //}
 }
Пример #4
0
        //DummyItem 意思是展开树节点时,显示子节点正在加载中的一个临时树节点。

        /// <summary>
        /// Checks whether a given tree node contains a dummy node to
        /// ensure it's rendered with an expander, and removes the node.
        /// </summary>
        /// <param name="treeNode">The node to be checked for dummy
        /// child nodes.</param>
        internal static void ClearDummyChildNode(TreeGridRow treeNode)
        {
            ////if the item has never been expanded yet, it contains a dummy
            ////node - replace that one and insert real data
            //if (ContainsDummyNode(treeNode))
            //{
            //    treeNode.Items.Clear();
            //}
        }
Пример #5
0
        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();

            var rowPresenter = ItemsControl.ItemsControlFromItemContainer(this) as TreeGridCellsPresenter;

            if (rowPresenter != null)
            {
                this._row = rowPresenter.Row;
            }
        }
Пример #6
0
        /// <summary>
        /// 树型控件中的 Id 获取方法不能直接使用 Id,而是应该:
        /// 尽量使用 TreeId,不支持时,再使用实体自己的 Id。
        /// </summary>
        /// <param name="item"></param>
        /// <returns></returns>
        private object GetId(TreeGridRow item)
        {
            var entity = item.DataContext;

            if (entity == null)
            {
                throw new InvalidOperationException("这个 TreeGridRow 还没有绑定实体,获取 Id 失败。");
            }

            return(GetId(entity));
        }
Пример #7
0
        private void RefreshRowNo(TreeGridRow row)
        {
            //目前为了简单起见,只支持表格模式下有行号。(因为在树型模式下,行号应该使用递归遍历后计算生成。)
            if (this.OnlyGridMode)
            {
                //不能直接使用 DataItemsSource,这是因为可能界面会对集合进行排序。
                //var item = GetEntity(row);
                //var rowNo = this.DataItemsSource.IndexOf(item) + 1;
                //row.RowNo = rowNo;

                row.RowNo = this.ItemContainerGenerator.IndexFromContainer(row) + 1;
            }
        }
Пример #8
0
        /// <summary>
        /// 尽量展开所有目标行的父行,并让目标行处于可视范围内。
        /// </summary>
        /// <param name="item">要显示的行对应的数据。</param>
        /// <returns>返回是否成功显示该数据对应的行。</returns>
        public bool ExpandToView(object item)
        {
            bool success = false;

            if (item != null)
            {
                //从最上层父开始搜索对应的生成的行,如果已经生成,则直接展开该行,
                //如果该行还没有生成,则在渲染布局中加入该id,该行在接下来生成时会自动展开。
                var         parents        = this.GetParentItemList(item);
                bool        stopFindingRow = false;
                TreeGridRow lastParentRow  = null;
                foreach (var parent in parents)
                {
                    _renderExpansion.Add(GetId(parent));

                    if (!stopFindingRow)
                    {
                        var parentRow = this.FindRow(parent);
                        if (parentRow == null)
                        {
                            stopFindingRow = true;
                        }
                        else
                        {
                            lastParentRow        = parentRow;
                            parentRow.IsExpanded = true;
                        }
                    }
                }

                //没有停止搜索,说明所有行都已经生成。
                if (!stopFindingRow)
                {
                    var selectedRow = this.SelectedRow;
                    if (selectedRow != null)
                    {
                        selectedRow.BringIntoView();
                        success = true;
                    }
                }

                //如果目标行并没有成功显示,则把最后可见的父行显示出来。
                if (!success && lastParentRow != null)
                {
                    lastParentRow.BringIntoView();
                }
            }

            return(success);
        }
Пример #9
0
 /// <summary>
 /// Copy from TreeView class.
 /// </summary>
 /// <param name="data"></param>
 /// <param name="newRow"></param>
 /// <param name="selected"></param>
 internal void ChangeSelection(object data, TreeGridRow newRow, bool selected)
 {
     //同步本对象的 SelectedItem 属性。
     if (selected)
     {
         this.SelectedItem = data;
     }
     else
     {
         if (this.SelectedItem == data)
         {
             this.SelectedItem = null;
         }
     }
 }
Пример #10
0
 /// <summary>
 /// 设置行对应的选中状态属性
 /// </summary>
 /// <param name="row"></param>
 /// <param name="isSelected"></param>
 internal void ModifyRowProperty(TreeGridRow row, bool isSelected)
 {
     if (this.IsChecking)
     {
         row.SetIsCheckedField(isSelected);
     }
     else
     {
         //然后,需要设置 TreeListItem.IsSelected 属性。
         //否则,会造成内部使用的 TreeView 的 SelectedItem 属性不变,但是高亮的状态已经被清除,
         //这时用户再次点击该行时,TreeView 的 SelectedItemChanged 事件不会发生,
         //也就不会发生整个 MTTG 的 SelectedItem 处理流程,造成无法选中该行。
         //具体情况见 bug:http://ipm.grandsoft.com.cn/issues/247260
         row.SetIsSelectedField(isSelected);
     }
 }
Пример #11
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);
                }
            }
        }
Пример #12
0
        /// <summary>
        /// Copies the <see cref="SortDescription"/> elements of
        /// the <see cref="NodeSortDescriptions"/> collection to
        /// a currently processed tree node. This method is being
        /// invoked during the initialization of a given node, and
        /// if the <see cref="NodeSortDescriptions"/> property
        /// is changed at runtime.<br/>
        /// If the <see cref="ItemCollection.SortDescriptions"/>
        /// collection of the submitted <paramref name="node"/> is
        /// not empty, it will be cleared.<br/>
        /// This method is always being invoked, even if the
        /// <see cref="NodeSortDescriptions"/> dependency property
        /// is null. If you want to apply a custom sorting mechanism,
        /// simply override this method.
        /// </summary>
        /// <param name="node">The currently processed node, if any.
        /// This parameter is null if sort parameters should be set
        /// on the tree's <see cref="ItemsControl.Items"/>
        /// collection itself.
        /// </param>
        private void ApplySorting(TreeGridRow node)
        {
            //check whether we're sorting on node or tree level
            var items = node == null ? this.Items : node.Items;

            using (items.DeferRefresh())
            {
                //clear existing sort directions, if there are any
                items.SortDescriptions.Clear();

                //copy new sort directions
                if (this.NodeSortDescriptions != null)
                {
                    foreach (var sd in this.NodeSortDescriptions)
                    {
                        items.SortDescriptions.Add(sd);
                    }
                }
            }
        }
Пример #13
0
        private void FindViewPort(TreeGridRow row)
        {
            var itemsControl = row.ParentItemsControl;

            if (itemsControl != null)
            {
                var scrollViewer = MSInternal.GetScrollHost(itemsControl);
                if (scrollViewer != null && scrollViewer.CanContentScroll)
                {
                    var itemsHost = MSInternal.GetItemsHost(itemsControl);
                    if (itemsHost is VirtualizingPanel)
                    {
                        this._viewPort = scrollViewer.Template.FindName(PART_ScrollContentPresenter, scrollViewer) as FrameworkElement;
                        if (this._viewPort == null)
                        {
                            this._viewPort = scrollViewer;
                        }
                    }
                }
            }
        }
Пример #14
0
        /*********************** 代码块解释 *********************************
         *
         * 树结点的选择事件处理
         *
         * 基类的此方法以一种防止 TreeView 重入的方式来同步 this.SelectedItem 到 TreeView.SelecteItem 上。
         * 并在最后调用 this.OnSelectedItemChanged 方法,以抛出路由事件。
         *
         * 注意这三个方法的顺序:
         * OnTreeViewSelectedItemChanged
         * OnSelectedItemPropertyChanged
         * RaiseSelectedItemChanged
         *
         **********************************************************************/

        /// <summary>
        /// Copy from TreeView class.
        /// </summary>
        /// <param name="collapsed"></param>
        internal void HandleSelectionOnCollapsed(TreeGridRow collapsed)
        {
            using (this.SelectionProcess.TryEnterProcess(TGSelectionProcess.Row_Collapsed))
            {
                if (this.SelectionProcess.Success)
                {
                    //目前只支持在单选的时候,提供此功能。
                    if (this.SelectParentOnCollapsed && this.SelectionModel.InnerItems.Count == 1)
                    {
                        var selectedRow = this.SelectedRow;
                        if (selectedRow != null && selectedRow != collapsed)
                        {
                            //检查 collapsed 是否为 selectedRow 的父行。
                            bool selectionInCollapsed = false;
                            for (var parent = selectedRow; parent != null; parent = parent.ParentRow)
                            {
                                //找到 collasped 对象
                                if (parent == collapsed)
                                {
                                    selectionInCollapsed = true;
                                    break;
                                }
                            }

                            if (selectionInCollapsed)
                            {
                                this.ChangeSelection(collapsed.DataContext, collapsed, true);

                                if (selectedRow.IsKeyboardFocusWithin)
                                {
                                    selectedRow.Focus();
                                    return;
                                }
                            }
                        }
                    }
                }
            }
        }
Пример #15
0
        /// <summary>
        /// 设置某行的选择状态,并级联选择
        /// </summary>
        /// <param name="row"></param>
        /// <param name="value"></param>
        internal void CheckRowWithCascade(TreeGridRow row, bool value)
        {
            if (!this.IsCheckingEnabled)
            {
                return;
            }

            var entity = row.DataContext;

            this.CheckingModel.MarkSelected(row, value);
            this.RasieCheckChanged(entity, value);

            //CascadeParent 模式下,需要把所有父对象选中。
            if (value && this.NeedCascade(CheckingCascadeMode.CascadeParent))
            {
                object parent = this.GetParentItem(entity);

                while (parent != null)
                {
                    var parentRow = this.FindRow(parent);
                    if (parentRow == null || parentRow.IsChecked)
                    {
                        break;
                    }

                    this.CheckingModel.MarkSelected(parentRow, true);
                    this.RasieCheckChanged(parent, true);

                    parent = this.GetParentItem(parent);
                }
            }

            //CascadeChildren 模式下,需要把所有子对象选中。
            if (this.NeedCascade(CheckingCascadeMode.CascadeChildren))
            {
                this.CheckChildrenRecur(entity, value);
            }
        }
Пример #16
0
        /// <summary>
        /// Removes listener for an item that is represented
        /// by  a given <paramref name="node"/> from the cache, and also
        /// processes all the node's descendants recursively.
        /// </summary>
        /// <param name="node">The node to be removed.</param>
        public void UnregisterListeners(TreeGridRow node)
        {
            lock (this)
            {
                //try to get the represented item
                object item = node.DataContext;
                if (item == null)
                {
                    return;
                }

                //get the item's observed child collection and
                //deregister it
                var itemKey = tree.GetId(item);
                RemoveCollectionFromCache(itemKey);

                foreach (TreeGridRow childNode in node.Items)
                {
                    //recursively deregister descendants by
                    //removing all child nodes
                    UnregisterListeners(childNode);
                }
            }
        }
Пример #17
0
 public TreeGridRowAutomationPeer(TreeGridRow owner)
     : base(owner)
 {
     this._owner = owner;
 }
Пример #18
0
            /// <summary>
            /// 设置某行的“选中”状态
            ///
            /// 维护两个底层属性:一个是选择项 List,一个是 row 的选择状态属性。
            /// </summary>
            /// <param name="row"></param>
            /// <param name="isSelected">是“选中”状态还是“未选中”状态。</param>
            internal void MarkSelected(TreeGridRow row, bool isSelected)
            {
                this.ModifyList(row.DataContext, isSelected);

                this.ModifyRowProperty(row, isSelected);
            }
Пример #19
0
 internal static bool IsDummyItem(TreeGridRow item)
 {
     return false;
     //return TreeGrid.GetEntity(item) == null;
 }
Пример #20
0
 /// <summary>
 /// Validates whether a given node contains a single dummy item,
 /// which was added to ensure the submitted tree node renders
 /// an expander.
 /// </summary>
 /// <param name="treeNode">The tree node to be validated.</param>
 /// <returns>True if the node contains a dummy item.</returns>
 internal static bool ContainsDummyNode(TreeGridRow treeNode)
 {
     return false;
     //return treeNode.Items.Count == 1 && TreeGrid.GetEntity(((TreeGridRow)treeNode.Items[0])) == null;
 }
Пример #21
0
        /// <summary>
        /// 树型控件中的 Id 获取方法不能直接使用 Id,而是应该:
        /// 尽量使用 TreeId,不支持时,再使用实体自己的 Id。
        /// </summary>
        /// <param name="item"></param>
        /// <returns></returns>
        private object GetId(TreeGridRow item)
        {
            var entity = item.DataContext;
            if (entity == null) throw new InvalidOperationException("这个 TreeGridRow 还没有绑定实体,获取 Id 失败。");

            return GetId(entity);
        }
Пример #22
0
 /// <summary>
 /// 开始编辑某行。
 /// </summary>
 /// <param name="row"></param>
 /// <param name="focusCell">编辑后,应该首先进入编辑状态的单元格。</param>
 public bool TryEditRow(TreeGridRow row, TreeGridCell focusCell)
 {
     return(this.TryEditRow(row, null, focusCell));
 }
Пример #23
0
 /// <summary>
 /// Validates whether a given node contains a single dummy item,
 /// which was added to ensure the submitted tree node renders
 /// an expander.
 /// </summary>
 /// <param name="treeNode">The tree node to be validated.</param>
 /// <returns>True if the node contains a dummy item.</returns>
 internal static bool ContainsDummyNode(TreeGridRow treeNode)
 {
     return(false);
     //return treeNode.Items.Count == 1 && TreeGrid.GetEntity(((TreeGridRow)treeNode.Items[0])) == null;
 }
Пример #24
0
        /// <summary>
        /// 开始编辑某行。
        /// </summary>
        /// <param name="row"></param>
        /// <param name="editingEventArgs">引发编辑的事件参数。</param>
        /// <param name="focusCell">编辑后,应该首先进入编辑状态的单元格。</param>
        internal bool TryEditRow(TreeGridRow row, RoutedEventArgs editingEventArgs, TreeGridCell focusCell)
        {
            var success = false;

            if (!this.IsReadOnly && this.EditingMode == TreeGridEditingMode.Row)
            {
                var item = row.DataContext;
                var selectedItems = this.SelectionModel.InnerItems;
                //由于点击任何一行的该列都会发生此事件,所以需要检测如果当前只选择了一列
                if (selectedItems.Count == 1 && item == selectedItems[0])
                {
                    //先退出之前行的编辑状态。
                    if (this._editingItem != item)
                    {
                        this.ExitRowEditing();

                        this._editingItem = item;
                    }

                    //focused 表示是否已经有单元格设置了焦点。
                    bool focused = focusCell != null;
                    var mouseArgs = editingEventArgs as MouseButtonEventArgs;

                    //设置所有单元格的编辑状态,及焦点。
                    var cells = row.TraverseCells();
                    foreach (var cell in cells)
                    {
                        //设置单元格的编辑状态
                        if (!cell.IsEditing && cell.Column.CanEdit(this._editingItem))
                        {
                            cell.SetIsEditingField(true);
                        }

                        //如果成功设置单元格的编辑状态,而且还没有设置单元格焦点,
                        //那么就通过鼠标的坐标来判断是否需要设置当前单元格的焦点。
                        if (!focused && mouseArgs != null && cell.IsEditing && cell.VisibleOnVirtualizing)
                        {
                            var position = mouseArgs.GetPosition(cell);
                            var cellPosition = new Rect(cell.RenderSize);
                            if (cellPosition.Contains(position))
                            {
                                cell.FocusOnEditing(editingEventArgs);
                                focused = true;
                            }
                        }
                    }

                    if (focusCell != null)
                    {
                        focusCell.FocusOnEditing(editingEventArgs);
                    }

                    //标记事件已经处理,防止事件继续冒泡导致引发 TreeGridRow.OnGotFocus 事件。
                    if (editingEventArgs != null) editingEventArgs.Handled = true;

                    success = true;
                }
            }

            return success;
        }
Пример #25
0
 /// <summary>
 /// 为指定的结点应用 <see cref="RowStyle"/> 样式。
 /// 
 /// 子类重写此方法用于应用自定义样式。
 /// </summary>
 /// <param name="treeNode">The node to be styled.</param>
 private void ApplyNodeStyle(TreeGridRow treeNode)
 {
     var style = this.RowStyle;
     if (style != null) treeNode.Style = style;
 }
Пример #26
0
            /// <summary>
            /// 设置某行的“选中”状态
            /// 
            /// 维护两个底层属性:一个是选择项 List,一个是 row 的选择状态属性。
            /// </summary>
            /// <param name="row"></param>
            /// <param name="isSelected">是“选中”状态还是“未选中”状态。</param>
            internal void MarkSelected(TreeGridRow row, bool isSelected)
            {
                this.ModifyList(row.DataContext, isSelected);

                this.ModifyRowProperty(row, isSelected);
            }
Пример #27
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)
                }
            }
        }
Пример #28
0
        /// <summary>
        /// 设置某行的选择状态,并级联选择
        /// </summary>
        /// <param name="row"></param>
        /// <param name="value"></param>
        internal void CheckRowWithCascade(TreeGridRow row, bool value)
        {
            if (!this.IsCheckingEnabled) { return; }

            var entity = row.DataContext;

            this.CheckingModel.MarkSelected(row, value);
            this.RasieCheckChanged(entity, value);

            //CascadeParent 模式下,需要把所有父对象选中。
            if (value && this.NeedCascade(CheckingCascadeMode.CascadeParent))
            {
                object parent = this.GetParentItem(entity);

                while (parent != null)
                {
                    var parentRow = this.FindRow(parent);
                    if (parentRow == null || parentRow.IsChecked) { break; }

                    this.CheckingModel.MarkSelected(parentRow, true);
                    this.RasieCheckChanged(parent, true);

                    parent = this.GetParentItem(parent);
                }
            }

            //CascadeChildren 模式下,需要把所有子对象选中。
            if (this.NeedCascade(CheckingCascadeMode.CascadeChildren))
            {
                this.CheckChildrenRecur(entity, value);
            }
        }
Пример #29
0
 private void FindViewPort(TreeGridRow row)
 {
     var itemsControl = row.ParentItemsControl;
     if (itemsControl != null)
     {
         var scrollViewer = MSInternal.GetScrollHost(itemsControl);
         if (scrollViewer != null && scrollViewer.CanContentScroll)
         {
             var itemsHost = MSInternal.GetItemsHost(itemsControl);
             if (itemsHost is VirtualizingPanel)
             {
                 this._viewPort = scrollViewer.Template.FindName(PART_ScrollContentPresenter, scrollViewer) as FrameworkElement;
                 if (this._viewPort == null)
                 {
                     this._viewPort = scrollViewer;
                 }
             }
         }
     }
 }
Пример #30
0
        /// <summary>
        /// 开始编辑某行。
        /// </summary>
        /// <param name="row"></param>
        /// <param name="editingEventArgs">引发编辑的事件参数。</param>
        /// <param name="focusCell">编辑后,应该首先进入编辑状态的单元格。</param>
        internal bool TryEditRow(TreeGridRow row, RoutedEventArgs editingEventArgs, TreeGridCell focusCell)
        {
            var success = false;

            if (!this.IsReadOnly && this.EditingMode == TreeGridEditingMode.Row)
            {
                var item          = row.DataContext;
                var selectedItems = this.SelectionModel.InnerItems;
                //由于点击任何一行的该列都会发生此事件,所以需要检测如果当前只选择了一列
                if (selectedItems.Count == 1 && item == selectedItems[0])
                {
                    //先退出之前行的编辑状态。
                    if (this._editingItem != item)
                    {
                        this.ExitRowEditing();

                        this._editingItem = item;
                    }

                    //focused 表示是否已经有单元格设置了焦点。
                    bool focused   = focusCell != null;
                    var  mouseArgs = editingEventArgs as MouseButtonEventArgs;

                    //设置所有单元格的编辑状态,及焦点。
                    var cells = row.TraverseCells();
                    foreach (var cell in cells)
                    {
                        //设置单元格的编辑状态
                        if (!cell.IsEditing && cell.Column.CanEdit(this._editingItem))
                        {
                            cell.SetIsEditingField(true);
                        }

                        //如果成功设置单元格的编辑状态,而且还没有设置单元格焦点,
                        //那么就通过鼠标的坐标来判断是否需要设置当前单元格的焦点。
                        if (!focused && mouseArgs != null && cell.IsEditing && cell.VisibleOnVirtualizing)
                        {
                            var position     = mouseArgs.GetPosition(cell);
                            var cellPosition = new Rect(cell.RenderSize);
                            if (cellPosition.Contains(position))
                            {
                                cell.FocusOnEditing(editingEventArgs);
                                focused = true;
                            }
                        }
                    }

                    if (focusCell != null)
                    {
                        focusCell.FocusOnEditing(editingEventArgs);
                    }

                    //标记事件已经处理,防止事件继续冒泡导致引发 TreeGridRow.OnGotFocus 事件。
                    if (editingEventArgs != null)
                    {
                        editingEventArgs.Handled = true;
                    }

                    success = true;
                }
            }

            return(success);
        }
Пример #31
0
        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();

            var rowPresenter = ItemsControl.ItemsControlFromItemContainer(this) as TreeGridCellsPresenter;
            if (rowPresenter != null) { this._row = rowPresenter.Row; }
        }
Пример #32
0
 internal static void CreateDummyItem(TreeGridRow treeNode)
 {
     ////clear items and insert dummy
     //treeNode.Items.Clear();
     //treeNode.Items.Add(this.CreateDummyItem());
 }
Пример #33
0
        /// <summary>
        /// Removes listener for an item that is represented
        /// by  a given <paramref name="node"/> from the cache, and also
        /// processes all the node's descendants recursively.
        /// </summary>
        /// <param name="node">The node to be removed.</param>
        public void UnregisterListeners(TreeGridRow node)
        {
            lock (this)
            {
                //try to get the represented item
                object item = node.DataContext;
                if (item == null) return;

                //get the item's observed child collection and
                //deregister it
                var itemKey = tree.GetId(item);
                RemoveCollectionFromCache(itemKey);

                foreach (TreeGridRow childNode in node.Items)
                {
                    //recursively deregister descendants by
                    //removing all child nodes
                    UnregisterListeners(childNode);
                }
            }
        }
Пример #34
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);
                }
            }
        }
Пример #35
0
 /// <summary>
 /// Copy from TreeView class.
 /// </summary>
 /// <param name="data"></param>
 /// <param name="newRow"></param>
 /// <param name="selected"></param>
 internal void ChangeSelection(object data, TreeGridRow newRow, bool selected)
 {
     //同步本对象的 SelectedItem 属性。
     if (selected)
     {
         this.SelectedItem = data;
     }
     else
     {
         if (this.SelectedItem == data)
         {
             this.SelectedItem = null;
         }
     }
 }
Пример #36
0
 internal static bool IsDummyItem(TreeGridRow item)
 {
     return(false);
     //return TreeGrid.GetEntity(item) == null;
 }
Пример #37
0
        /*********************** 代码块解释 *********************************
         *
         * 树结点的选择事件处理
         *
         * 基类的此方法以一种防止 TreeView 重入的方式来同步 this.SelectedItem 到 TreeView.SelecteItem 上。
         * 并在最后调用 this.OnSelectedItemChanged 方法,以抛出路由事件。
         *
         * 注意这三个方法的顺序:
         * OnTreeViewSelectedItemChanged
         * OnSelectedItemPropertyChanged
         * RaiseSelectedItemChanged
         *
        **********************************************************************/
        /// <summary>
        /// Copy from TreeView class.
        /// </summary>
        /// <param name="collapsed"></param>
        internal void HandleSelectionOnCollapsed(TreeGridRow collapsed)
        {
            using (this.SelectionProcess.TryEnterProcess(TGSelectionProcess.Row_Collapsed))
            {
                if (this.SelectionProcess.Success)
                {
                    //目前只支持在单选的时候,提供此功能。
                    if (this.SelectParentOnCollapsed && this.SelectionModel.InnerItems.Count == 1)
                    {
                        var selectedRow = this.SelectedRow;
                        if (selectedRow != null && selectedRow != collapsed)
                        {
                            //检查 collapsed 是否为 selectedRow 的父行。
                            bool selectionInCollapsed = false;
                            for (var parent = selectedRow; parent != null; parent = parent.ParentRow)
                            {
                                //找到 collasped 对象
                                if (parent == collapsed)
                                {
                                    selectionInCollapsed = true;
                                    break;
                                }
                            }

                            if (selectionInCollapsed)
                            {
                                this.ChangeSelection(collapsed.DataContext, collapsed, true);

                                if (selectedRow.IsKeyboardFocusWithin)
                                {
                                    selectedRow.Focus();
                                    return;
                                }
                            }
                        }
                    }
                }
            }
        }
Пример #38
0
 internal static void CreateDummyItem(TreeGridRow treeNode)
 {
     ////clear items and insert dummy
     //treeNode.Items.Clear();
     //treeNode.Items.Add(this.CreateDummyItem());
 }
Пример #39
0
 /// <summary>
 /// 设置行对应的选中状态属性
 /// </summary>
 /// <param name="row"></param>
 /// <param name="isSelected"></param>
 internal void ModifyRowProperty(TreeGridRow row, bool isSelected)
 {
     if (this.IsChecking)
     {
         row.SetIsCheckedField(isSelected);
     }
     else
     {
         //然后,需要设置 TreeListItem.IsSelected 属性。
         //否则,会造成内部使用的 TreeView 的 SelectedItem 属性不变,但是高亮的状态已经被清除,
         //这时用户再次点击该行时,TreeView 的 SelectedItemChanged 事件不会发生,
         //也就不会发生整个 MTTG 的 SelectedItem 处理流程,造成无法选中该行。
         //具体情况见 bug:http://ipm.grandsoft.com.cn/issues/247260
         row.SetIsSelectedField(isSelected);
     }
 }
Пример #40
0
        /// <summary>
        /// Copies the <see cref="SortDescription"/> elements of
        /// the <see cref="NodeSortDescriptions"/> collection to
        /// a currently processed tree node. This method is being
        /// invoked during the initialization of a given node, and
        /// if the <see cref="NodeSortDescriptions"/> property 
        /// is changed at runtime.<br/>
        /// If the <see cref="ItemCollection.SortDescriptions"/>
        /// collection of the submitted <paramref name="node"/> is
        /// not empty, it will be cleared.<br/>
        /// This method is always being invoked, even if the
        /// <see cref="NodeSortDescriptions"/> dependency property
        /// is null. If you want to apply a custom sorting mechanism,
        /// simply override this method.
        /// </summary>
        /// <param name="node">The currently processed node, if any.
        /// This parameter is null if sort parameters should be set
        /// on the tree's <see cref="ItemsControl.Items"/>
        /// collection itself.
        /// </param>
        private void ApplySorting(TreeGridRow node)
        {
            //check whether we're sorting on node or tree level
            var items = node == null ? this.Items : node.Items;

            using (items.DeferRefresh())
            {
                //clear existing sort directions, if there are any
                items.SortDescriptions.Clear();

                //copy new sort directions
                if (this.NodeSortDescriptions != null)
                {
                    foreach (var sd in this.NodeSortDescriptions)
                    {
                        items.SortDescriptions.Add(sd);
                    }
                }
            }
        }
Пример #41
0
        private void RefreshRowNo(TreeGridRow row)
        {
            //目前为了简单起见,只支持表格模式下有行号。(因为在树型模式下,行号应该使用递归遍历后计算生成。)
            if (this.OnlyGridMode)
            {
                //不能直接使用 DataItemsSource,这是因为可能界面会对集合进行排序。
                //var item = GetEntity(row);
                //var rowNo = this.DataItemsSource.IndexOf(item) + 1;
                //row.RowNo = rowNo;

                row.RowNo = this.ItemContainerGenerator.IndexFromContainer(row) + 1;
            }
        }
Пример #42
0
 /// <summary>
 /// 开始编辑某行。
 /// </summary>
 /// <param name="row"></param>
 /// <param name="focusCell">编辑后,应该首先进入编辑状态的单元格。</param>
 public bool TryEditRow(TreeGridRow row, TreeGridCell focusCell)
 {
     return this.TryEditRow(row, null, focusCell);
 }