Can I request a feature change so that when a grid's TabNavigation property is set to NextControlOnLastCell, that the last cell part of that means the last editable cell? Either that or a new enum member like NextControlOnLastEditableCell? We have cases where the last cell of the grid is not editable and cannot be tabbed into (by user request). When we are on the last cell that allows edits, we'd like the tab key to send user to next control. It does not and we are currently forced to workaround in sloppy fashion...
Inherited UltraGrid Class w/likely imperfect methods for determining if on the last editable cell in grid: .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: Consolas, "Courier New", Courier, Monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }
/// <summary> /// Returns true if the current active cell is the last editable cell in the grid /// </summary> /// <returns></returns> public bool IsLastEditableCellInGrid() { return IsLastEditableCellInGrid(this.ActiveCell); } /// <summary> /// Determines whether specified <paramref name="cell"/> is the last editable cell in the grid /// </summary> /// <param name="cell">The cell.</param> /// <returns> /// <c>true</c> if [is last editable cell in grid] [the specified cell]; otherwise, <c>false</c>. /// </returns> public bool IsLastEditableCellInGrid(UltraGridCell cell) { if (null != cell) { UltraGridRow row = this.ActiveRow; int cellStartIndex = cell.Column.Index + 1; while (null != row) { for (int i = cellStartIndex; i < cell.Column.Band.Columns.Count; i++) { UltraGridCell tempCell = row.Cells[i]; if (!tempCell.Hidden && !tempCell.Column.Hidden && IsCellEditable(tempCell)) { return false; } } row = GetNextRow(row); cellStartIndex = 0; } return true; } return false; } /// <summary> /// Determines whether specified cell is editable /// </summary> /// <param name="cell">The cell.</param> /// <returns> /// <c>true</c> if [is cell editable] [the specified cell]; otherwise, <c>false</c>. /// </returns> public bool IsCellEditable(UltraGridCell cell) { if (!this.Enabled || this.DisplayLayout.Override.AllowUpdate == DefaultableBoolean.False || this.ReadOnly || cell.Activation != Activation.AllowEdit || cell.Column.CellActivation != Activation.AllowEdit) { return false; } else { return true; } } /// <summary> /// Gets the next row in grid based on specified <paramref name="initialRow"/> /// </summary> /// <param name="initialRow">The initial row.</param> /// <returns></returns> public UltraGridRow GetNextRow(UltraGridRow initialRow) { //Calling various PerformAction enumerations on the grid itself would result in more straightforward code, //but any of the PerformAction options that change the ActiveRow for the grid also cause the entire row to //flash highlighted as it changes to be the selected row. Since we're setting the new cell into Edit mode, //the highlight ends up in the cell by the time we are done, not the entire row, so the user sees the //entire row flash highlighted for a second, and it's quite jarring and unattractive (and setting BeginUpdate //and EndUpdate to suppress the flash does indeed fix the flash, but it introduces an unacceptable delay when //moving from row to row). So this code to manually find the next row might be more complex than //some of the other ways of doing it, but the resulting UI is much nicer. UltraGridRow newRow = null; UltraGridRow checkRow = initialRow; if (checkRow.HasChild() == true) { newRow = checkRow.GetChild(ChildRow.First); } else if (checkRow.HasNextSibling() == true) { newRow = checkRow.GetSibling(SiblingRow.Next); } else if (checkRow.ParentRow != null) { do { if (checkRow.ParentRow != null) { checkRow = checkRow.ParentRow; } else { break; } } while (checkRow.HasNextSibling() == false); if (checkRow.HasNextSibling() == true) { newRow = checkRow.GetSibling(SiblingRow.Next); } } if ((newRow != null) && (newRow != initialRow) && (IsRowAccessible(newRow) == false)) { newRow = GetNextRow(newRow); } if ((newRow != null) && (newRow != initialRow) && (IsRowAccessible(newRow) == true)) { return newRow; } else { return null; } } /// <summary> /// Determines whether specified <paramref name="row"/> is accessible /// (i.e. ancestors expanded, not hidden, not filtered out etc.) /// </summary> /// <param name="row">The row.</param> /// <returns> /// <c>true</c> if [is row accessible] [the specified row]; otherwise, <c>false</c>. /// </returns> public bool IsRowAccessible(UltraGridRow row) { if ((row.AllAncestorsExpanded == false) || (row.HiddenResolved == true) || (row.IsFilteredOut == true)) { return false; } else { return true; } }
protected override bool ProcessCmdKey(ref Message msg, Keys keyData) { bool baseResult = base.ProcessCmdKey(ref msg, keyData); if (keyData == Keys.Tab) { //HACK alert // yuck, w/tabnavigation of nextcontrolonlastcell infragistics won't tab to next // control unless we are physically on the last cell, not on last editable cell if (ControlHelper.GetActiveControl(this) == uxVariablesUltraGrid) { if (uxVariablesUltraGrid.IsLastEditableCellInGrid()) { if (uxDistributionUltraGrid.Visible && uxDistributionUltraGrid.Enabled) { //currently toolstrip doesn't allow tabstop but this will cause //grid to focus correctly so leave for now //uxDistributionUltraGrid.Focus(); toolStrip1.Focus(); } } } } return baseResult; }
That seems like a reasonable theory. The logic which does the tabbing is probably not accounting for the case where the entire following row cannot be tabbed into. If that is the case, then it's a bug.
I have attached a sample project here that demonstrates the problem. I will file a bug/request for this problem. I think I know why the UltraGrid is not tabbing to the next control. In our situation, cells are dynamically enabled/disabled. In this particular case, nothing in the last row of the grid is enabled/focusable at all. If I change data so something on the last row is enabled, it works. Looks like UltraGrid only does the tab check on the last row. Regardless of whether the current row is the last row or not, the last editable cell in the grid should trigger tabbing out.
We are using version 8.1.20081.2013. Nothing happens when we press Tab on the last editable cell. If I can make the time I'll try to create sample project to demonstrate behavior and submit bug if it still happens there.
What you are describing is the correct behavior. That is... if you press the tab key and there are no more cells that can be tabbed into, then the focus should shift to the next control.
If the you are pressing tab and nothing happens, then it's a bug and you should make sure you have the latest Hot Fix. I thought this particular issue was fixed years ago. Are you using a really old version of the grid?
If you have the latest Hot Fix and that does not help, then you should Submit an incident to Infragistics Developer Support and include a small sample project demonstrating the problem.