/// <summary> /// 滚动到指定列,等待其生成完毕后,返回该行中的某一个单元格。如果还没有找到,则抛出异常。 /// </summary> /// <param name="column"></param> /// <returns></returns> public TreeGridCell ScrollToCell(TreeGridColumn column) { var grid = this.TreeGrid; if (grid != null && this.CellsPresenter != null) { var columnIndex = grid.Columns.IndexOf(column); if (columnIndex >= 0) { int i = 0; TreeGridCell cell = null; while (cell == null && i++ < 1000)//1000 进入防止死循环 { grid.BringColumnIntoView(columnIndex); Dispatcher.Invoke(DispatcherPriority.Background, (DispatcherOperationCallback) delegate(object unused) { cell = this.CellsPresenter .ItemContainerGenerator.ContainerFromIndex(columnIndex) as TreeGridCell; return(null); }, null); } return(cell); } } throw new NotSupportedException("无法滚动到指定的列:" + column.HeaderLabel + ",可能当前行还没有加载完成。"); }
/// <summary> /// 尝试开始编辑某一个单元格。 /// </summary> /// <param name="cell"></param> /// <param name="editingEventArgs"></param> /// <returns></returns> internal bool TryEditCell(TreeGridCell cell, RoutedEventArgs editingEventArgs) { if (this.CanEditCell(cell)) { this.EditCell(cell, editingEventArgs); return(true); } return(false); }
/// <summary> /// 尝试找到指定对象的指定单元格。 /// 如果该行该列正处于虚拟化中,则返回 null。 /// </summary> /// <param name="item"></param> /// <param name="column"></param> /// <returns></returns> public TreeGridCell FindCell(object item, TreeGridColumn column) { TreeGridCell cell = null; var row = this.FindRow(item); if (row != null) { cell = row.FindCell(column); } return(cell); }
/// <summary> /// 修改表格的编辑状态,并让某个单元格进入编辑状态。 /// </summary> /// <param name="editingCell"></param> /// <param name="editingEventArgs">引发此操作的事件参数。可为 null。</param> private void EditCellCore(TreeGridCell editingCell, RoutedEventArgs editingEventArgs) { this._editingItem = editingCell.Row.DataContext; this._editingColumn = editingCell.Column; editingCell.SetIsEditingField(true); editingCell.FocusOnEditing(editingEventArgs); //需要把这个事件处理掉,模仿:DataGridCell.OnAnyMouseButtonDown。 if (editingEventArgs != null) { editingEventArgs.Handled = true; } }
private void EditCell(TreeGridCell cell, RoutedEventArgs editingEventArgs) { //如果当前已经开始编辑某个单元格 if (this._editingItem != null && this._editingColumn != null) { if (this._editingColumn != cell.Column || this._editingItem != cell.Row.DataContext) { this.ExitCellEditing(); this.EditCellCore(cell, editingEventArgs); } } else { this.EditCellCore(cell, editingEventArgs); } }
/// <summary> /// 找到该行中的某一个单元格 /// </summary> /// <param name="column"></param> /// <returns></returns> public TreeGridCell FindCell(TreeGridColumn column) { TreeGridCell cell = null; if (this.CellsPresenter != null) { var grid = this.TreeGrid; if (grid != null) { var columnIndex = grid.Columns.IndexOf(column); if (columnIndex >= 0) { cell = this.CellsPresenter .ItemContainerGenerator.ContainerFromIndex(columnIndex) as TreeGridCell; } } } return(cell); }
private void PrepareCell(TreeGridCell cell, TreeGridColumn column) { cell.Column = column; if (column.CellStyle != null) { cell.Style = column.CellStyle; } cell.UpdateContent(false); //IsEditing var row = this.Row; if (row != null) { var grid = row.TreeGrid; //当前行是表格中正在编辑的行 if (grid != null && this.DataContext == grid.EditingItem) { //整行编辑、或者正在编辑该单元格 if (grid.EditingMode == TreeGridEditingMode.Row || column == grid.EditingColumn) { if (cell.Column.CanEdit(cell.DataContext)) { cell.SetIsEditingField(true); //this.RestoreEditingContent(cell, column, grid); } } } } //Automation var headerLabel = column.HeaderLabel; if (!string.IsNullOrEmpty(headerLabel)) { AutomationProperties.SetName(cell, headerLabel); } }
/// <summary> /// 返回是否可以成功编辑某个单元格。 /// /// 以下情况下,不能编辑: /// * 整个表格不能进行编辑。 /// * 该单元格所在的列不能进行编辑。 /// * 表格没有处于 CellEditing 模式下。 /// * 当前未选择唯一行(单选状态下可编辑)。 /// </summary> /// <param name="cell"></param> /// <returns></returns> private bool CanEditCell(TreeGridCell cell) { var success = false; if (!this.IsReadOnly && this.EditingMode == TreeGridEditingMode.Cell) { var column = cell.Column; //如果是列是只读状态,就不能进入编辑状态。 if (cell.Column != null && cell.Column.CanEdit(cell.DataContext)) { var row = cell.Row; var selectedItems = this.SelectionModel.InnerItems; //由于点击任何一行的该列都会发生此事件,所以需要检测如果当前只选择了一列 if (row != null && selectedItems.Count == 1 && row.DataContext == selectedItems[0]) { success = true; } } } return(success); }
///// <summary> ///// 编辑模式下的编辑元素,保存起来; ///// 当单元格再次被生成时,直接使用这些元素而不再次生成。这样可以防止用户信息的丢失。 ///// ///// 详见:PrepareCell & ClearCell ///// </summary> //private Dictionary<TreeGridColumn, UIElement> _editingElements; /// <summary> /// 当虚拟化 Panel 重新使用一个单元格时,需要尝试恢复它的焦点信息。 /// </summary> /// <param name="cell"></param> internal void RestoreEditingCellFocus(TreeGridCell cell) { var row = this.Row; if (row != null) { var grid = row.TreeGrid; if (grid != null && grid.EditingItem != null && grid.EditingItem == this.DataContext) { //目前只支持单元格编辑模式下的焦点恢复。 if (grid.EditingMode == TreeGridEditingMode.Cell && cell.Column == grid.EditingColumn) { var content = cell.Content as UIElement; if (content != null) { content.Focus(); } } } } }
//protected override void ClearContainerForItemOverride(DependencyObject element, object item) //{ // var cell = element as TreeGridCell; // base.ClearContainerForItemOverride(element, item); // this.ReserveEditingContent(cell); //} //private void ReserveEditingContent(TreeGridCell cell) //{ // //IsEditing:把编辑控件存储下来。 // var row = this.Row; // if (row != null) // { // var grid = row.TreeGrid; // if (grid != null && this.DataContext == grid.EditingItem) // { // //非回收模式下,需要把 // if (!grid.IsRecycleMode) // { // if (grid.EditingMode == TreeGridEditingMode.Row || cell.Column == grid.EditingColumn) // { // if (this._editingElements == null) // { // this._editingElements = new Dictionary<TreeGridColumn, UIElement>(); // } // this._editingElements[cell.Column] = cell.Content as UIElement; // } // } // } // } //} private void RestoreEditingContent(TreeGridCell cell, TreeGridColumn column, TreeGrid grid) { ////非回收模式下,为了返回原来的焦点,需要使用之前的编辑控件。 //if (!grid.IsRecycleMode) //{ // //如果之前已经生成了编辑控件,则使用老的控件,这样可以继续之前的编辑信息。 // if (this._editingElements != null) // { // UIElement content = null; // if (this._editingElements.TryGetValue(column, out content)) // { // cell.UpdateContent(content); // //column.PrepareElementForEdit(content as FrameworkElement, null); // //var res = content.Focus(); // //Debug.WriteLine(" content.IsVisible:" + content.IsVisible // // + " content.Focus():" + res // // + " KeyboardFocus:" + Keyboard.FocusedElement.GetType().FullName // // ); // this._editingElements.Remove(column); // } // } //} }
/// <summary> /// 开始编辑某行。 /// </summary> /// <param name="row"></param> /// <param name="focusCell">编辑后,应该首先进入编辑状态的单元格。</param> public bool TryEditRow(TreeGridRow row, TreeGridCell focusCell) { return this.TryEditRow(row, null, focusCell); }
//protected override void ClearContainerForItemOverride(DependencyObject element, object item) //{ // var cell = element as TreeGridCell; // base.ClearContainerForItemOverride(element, item); // this.ReserveEditingContent(cell); //} //private void ReserveEditingContent(TreeGridCell cell) //{ // //IsEditing:把编辑控件存储下来。 // var row = this.Row; // if (row != null) // { // var grid = row.TreeGrid; // if (grid != null && this.DataContext == grid.EditingItem) // { // //非回收模式下,需要把 // if (!grid.IsRecycleMode) // { // if (grid.EditingMode == TreeGridEditingMode.Row || cell.Column == grid.EditingColumn) // { // if (this._editingElements == null) // { // this._editingElements = new Dictionary<TreeGridColumn, UIElement>(); // } // this._editingElements[cell.Column] = cell.Content as UIElement; // } // } // } // } //} private void RestoreEditingContent(TreeGridCell cell, TreeGridColumn column, TreeGrid grid) { ////非回收模式下,为了返回原来的焦点,需要使用之前的编辑控件。 //if (!grid.IsRecycleMode) //{ // //如果之前已经生成了编辑控件,则使用老的控件,这样可以继续之前的编辑信息。 // if (this._editingElements != null) // { // UIElement content = null; // if (this._editingElements.TryGetValue(column, out content)) // { // cell.UpdateContent(content); // //column.PrepareElementForEdit(content as FrameworkElement, null); // //var res = content.Focus(); // //Debug.WriteLine(" content.IsVisible:" + content.IsVisible // // + " content.Focus():" + res // // + " KeyboardFocus:" + Keyboard.FocusedElement.GetType().FullName // // ); // this._editingElements.Remove(column); // } // } //} }
private void PrepareCell(TreeGridCell cell, TreeGridColumn column) { cell.Column = column; if (column.CellStyle != null) { cell.Style = column.CellStyle; } cell.UpdateContent(false); //IsEditing var row = this.Row; if (row != null) { var grid = row.TreeGrid; //当前行是表格中正在编辑的行 if (grid != null && this.DataContext == grid.EditingItem) { //整行编辑、或者正在编辑该单元格 if (grid.EditingMode == TreeGridEditingMode.Row || column == grid.EditingColumn) { if (cell.Column.CanEdit(cell.DataContext)) { cell.SetIsEditingField(true); //this.RestoreEditingContent(cell, column, grid); } } } } //Automation var headerLabel = column.HeaderLabel; if (!string.IsNullOrEmpty(headerLabel)) { AutomationProperties.SetName(cell, headerLabel); } }
///// <summary> ///// 编辑模式下的编辑元素,保存起来; ///// 当单元格再次被生成时,直接使用这些元素而不再次生成。这样可以防止用户信息的丢失。 ///// ///// 详见:PrepareCell & ClearCell ///// </summary> //private Dictionary<TreeGridColumn, UIElement> _editingElements; /// <summary> /// 当虚拟化 Panel 重新使用一个单元格时,需要尝试恢复它的焦点信息。 /// </summary> /// <param name="cell"></param> internal void RestoreEditingCellFocus(TreeGridCell cell) { var row = this.Row; if (row != null) { var grid = row.TreeGrid; if (grid != null && grid.EditingItem != null && grid.EditingItem == this.DataContext) { //目前只支持单元格编辑模式下的焦点恢复。 if (grid.EditingMode == TreeGridEditingMode.Cell && cell.Column == grid.EditingColumn) { var content = cell.Content as UIElement; if (content != null) content.Focus(); } } } }
/// <summary> /// 尝试开始编辑某一个单元格。 /// </summary> /// <param name="cell"></param> /// <param name="editingEventArgs"></param> /// <returns></returns> internal bool TryEditCell(TreeGridCell cell, RoutedEventArgs editingEventArgs) { if (this.CanEditCell(cell)) { this.EditCell(cell, editingEventArgs); return true; } return false; }
/// <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); }
/// <summary> /// 修改表格的编辑状态,并让某个单元格进入编辑状态。 /// </summary> /// <param name="editingCell"></param> /// <param name="editingEventArgs">引发此操作的事件参数。可为 null。</param> private void EditCellCore(TreeGridCell editingCell, RoutedEventArgs editingEventArgs) { this._editingItem = editingCell.Row.DataContext; this._editingColumn = editingCell.Column; editingCell.SetIsEditingField(true); editingCell.FocusOnEditing(editingEventArgs); //需要把这个事件处理掉,模仿:DataGridCell.OnAnyMouseButtonDown。 if (editingEventArgs != null) { editingEventArgs.Handled = true; } }
/// <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; }
/// <summary> /// 返回是否可以成功编辑某个单元格。 /// /// 以下情况下,不能编辑: /// * 整个表格不能进行编辑。 /// * 该单元格所在的列不能进行编辑。 /// * 表格没有处于 CellEditing 模式下。 /// * 当前未选择唯一行(单选状态下可编辑)。 /// </summary> /// <param name="cell"></param> /// <returns></returns> private bool CanEditCell(TreeGridCell cell) { var success = false; if (!this.IsReadOnly && this.EditingMode == TreeGridEditingMode.Cell) { var column = cell.Column; //如果是列是只读状态,就不能进入编辑状态。 if (cell.Column != null && cell.Column.CanEdit(cell.DataContext)) { var row = cell.Row; var selectedItems = this.SelectionModel.InnerItems; //由于点击任何一行的该列都会发生此事件,所以需要检测如果当前只选择了一列 if (row != null && selectedItems.Count == 1 && row.DataContext == selectedItems[0]) { success = true; } } } return success; }
/// <summary> /// 尝试通知本树型控件编辑某个单元格。 /// </summary> /// <param name="cell"></param> /// <returns>返回是否成功进入编辑状态</returns> public bool TryEditCell(TreeGridCell cell) { return this.TryEditCell(cell, null); }
/// <summary> /// 在编辑控件按 Tab 切换到下一列 /// </summary> /// <param name="cell"></param> /// <param name="moveNext">是向后编辑还是向前编辑。</param> /// <param name="e"></param> /// <param name="firstStarted"></param> internal void EditNextColumnOnTabKey(TreeGridCell cell, bool moveNext, KeyEventArgs e, TreeGridColumn firstStarted) { var grid = this.TreeGrid; var columns = grid.Columns; var index = columns.IndexOf(this); index += moveNext ? 1 : -1; //循环:如果是最后一个,则使用第一个;如果是第一个,则使用最后一个。 if (index >= columns.Count) { index = 0; } else if (index < 0) { index = columns.Count - 1; } //尝试编辑 var row = cell.Row; if (row != null) { var nextColumn = columns[index] as TreeGridColumn; //如果要编辑的单元格和起始单元格是同一个格子,则已经循环了一次,不需要继续了。 if (nextColumn == firstStarted) return; grid.BringColumnIntoView(index); var nextCell = row.FindCell(nextColumn); if (nextCell != null) { bool success = false; if (grid.EditingMode == TreeGridEditingMode.Cell) { success = grid.TryEditCell(nextCell, e); } else { //行模式下,只是把焦点移到下一个单元格即可。 if (nextCell.IsEditing) { nextCell.FocusOnEditing(e); success = true; } } if (success) { e.Handled = true; return; } //如果 nextCell 编辑失败,并且不是循环第二次,则继续编辑下一个。 nextColumn.EditNextColumnOnTabKey(nextCell, moveNext, e, firstStarted); } } }
/// <summary> /// 尝试通知本树型控件编辑某个单元格。 /// </summary> /// <param name="cell"></param> /// <returns>返回是否成功进入编辑状态</returns> public bool TryEditCell(TreeGridCell cell) { return(this.TryEditCell(cell, null)); }
private void EditCell(TreeGridCell cell, RoutedEventArgs editingEventArgs) { //如果当前已经开始编辑某个单元格 if (this._editingItem != null && this._editingColumn != null) { if (this._editingColumn != cell.Column || this._editingItem != cell.Row.DataContext) { this.ExitCellEditing(); this.EditCellCore(cell, editingEventArgs); } } else { this.EditCellCore(cell, editingEventArgs); } }
/// <summary> /// 开始编辑某行。 /// </summary> /// <param name="row"></param> /// <param name="focusCell">编辑后,应该首先进入编辑状态的单元格。</param> public bool TryEditRow(TreeGridRow row, TreeGridCell focusCell) { return(this.TryEditRow(row, null, focusCell)); }
public MTTGCellAutomationPeer(TreeGridCell owner) : base(owner) { }
public MTTGCellAutomationPeer(TreeGridCell owner) : base(owner) { }
/// <summary> /// 在编辑控件按 Tab 切换到下一列 /// </summary> /// <param name="cell"></param> /// <param name="moveNext">是向后编辑还是向前编辑。</param> /// <param name="e"></param> /// <param name="firstStarted"></param> internal void EditNextColumnOnTabKey(TreeGridCell cell, bool moveNext, KeyEventArgs e, TreeGridColumn firstStarted) { var grid = this.TreeGrid; var columns = grid.Columns; var index = columns.IndexOf(this); index += moveNext ? 1 : -1; //循环:如果是最后一个,则使用第一个;如果是第一个,则使用最后一个。 if (index >= columns.Count) { index = 0; } else if (index < 0) { index = columns.Count - 1; } //尝试编辑 var row = cell.Row; if (row != null) { var nextColumn = columns[index] as TreeGridColumn; //如果要编辑的单元格和起始单元格是同一个格子,则已经循环了一次,不需要继续了。 if (nextColumn == firstStarted) { return; } grid.BringColumnIntoView(index); var nextCell = row.FindCell(nextColumn); if (nextCell != null) { bool success = false; if (grid.EditingMode == TreeGridEditingMode.Cell) { success = grid.TryEditCell(nextCell, e); } else { //行模式下,只是把焦点移到下一个单元格即可。 if (nextCell.IsEditing) { nextCell.FocusOnEditing(e); success = true; } } if (success) { e.Handled = true; return; } //如果 nextCell 编辑失败,并且不是循环第二次,则继续编辑下一个。 nextColumn.EditNextColumnOnTabKey(nextCell, moveNext, e, firstStarted); } } }