带良好工具提示的DataGrid






4.65/5 (8投票s)
2005年9月29日
4分钟阅读

91392

1502
一个 DataGrid,可在排序后在每个单元格上显示正确的 ToolTip,并在单元格正在编辑时仍显示 ToolTip。
目录
- 引言
- 显示正确行的 ToolTip
- 显示选定的 DataGridTextBoxColumn 单元格的 ToolTip
- 显示正在编辑的 DataGridBoolColumn 单元格的 ToolTip
- DataGridBoolColumn 问题的其他方法
- 尊重 DataGridColumnStyle 的 NullText
- 历史
引言
在显示 DataGrid
单元格内容时,在显示 ToolTip
方面存在一些问题
- 没有明显的方法可以显示
DataGrid
单元格内容的ToolTip
。 - 当
DataGrid
被排序时,ToolTip
需要在排序后与正确的单元格相关联。 - 当选择一个
DataGridTextBoxColumn
单元格时,该单元格的事件可能不会触发,因为该单元格被DataGridTextBox
覆盖。 - 当
DataGridBoolColumn
中的单元格正在修改时,很难获取修改后的值。
这些问题会影响 .NET 1.1 和 2.0 中的 DataGrid
。2.0 的 DataGridView
使得显示 ToolTip
变得容易得多,但一些开发人员出于历史原因必须继续使用 1.1,或者可能不想费力地将他们的 DataGrid
移植到 DataGridView
。
本文介绍如何使用 DataGrid
单元格中的 ToolTip
来解决上述问题。
注意:在下面的示例中,为了清晰起见,已删除或合并了一些详细信息。请参阅源 Zip 文件以获取更完整的示例。
显示正确行的 ToolTip
在 DataGrid
事件处理程序中,使用 DataGrid.HitTestInfo
获取 DataGrid
中的目标行和列,并使用 CurrencyManager
获取数据源中相应的行和列。如果 DataGrid
中允许排序,DataGrid.HitTestInfo
返回的行号可能指向数据源中的不同行。例如,DataGrid
中显示的第三行可能是数据源中的第一行。HitTestInfo
返回该行在 DataGrid
中显示的索引;CurrencyManager
将该索引映射到数据源的行。一旦找到正确的源单元格,就可以轻松地将 ToolTip
设置为该单元格的内容。
private void GridTest_MouseMove(object sender, MouseEventArgs e)
{
// Determine which cell to inspect.
DataGrid.HitTestInfo hitInfo = gridTest.HitTest(new Point(e.X, e.Y));
CurrencyManager hitManager = (CurrencyManager)
this.BindingContext[gridTest.DataSource, gridTest.DataMember];
// If current target is valid cell, display contents in ToolTip.
if (hitInfo.Row < hitManager.List.Count &&
hitInfo.Type == DataGrid.HitTestType.Cell &&
hitManager.List is DataView)
{
// Use CurrencyManager to get DataRowView corresponding to data
// source's row.
DataRowView view = ((DataView)hitManager.List)[hitInfo.Row];
// Now that row is available, set ToolTip to cell's contents or,
// if cell is empty, to null indicator.
string tipText =
view.Row.IsNull(hitInfo.Column) ? "(null)" :
view.Row[hitInfo.Column].ToString();
toolTipTest.SetToolTip(gridTest, tipText);
}
}
显示选定的 DataGridTextBoxColumn 单元格的 ToolTip
当选择一个 DataGridTextBoxColumn
单元格时,该单元格的 DataGridTextBox
会接管。它覆盖了单元格的很大一部分,以至于该单元格中的许多 DataGrid
事件都不太可能触发。要在此情况下显示 ToolTip
,请为 DataGrid
中的每个 DataGridTextBox
分配一个事件处理程序,并使用该事件处理程序显示 ToolTip
。
private void InitializeControls()
{
// Assign MouseMove event handlers to all DataGridTextBoxes in DataGrid
for (int tableIndex = 0; tableIndex < gridTest.TableStyles.Count;
tableIndex++)
{
DataGridTableStyle tableStyle = gridTest.TableStyles[tableIndex];
for (int columnIndex = 0; columnIndex <
tableStyle.GridColumnStyles.Count; columnIndex++)
{
DataGridTextBoxColumn columnStyle =
tableStyle.GridColumnStyles[columnIndex] as DataGridTextBoxColumn;
// If the column is a DataGridTextBoxColumn (i.e. not null),
// assign MouseMove event handler to its TextBox.
if (columnStyle != null)
{
columnStyle.TextBox.MouseMove +=
new MouseEventHandler(this.TextBox_MouseMove);
}
}
}
}
在事件处理程序中,使用 DataGridTextBox
的文本作为 ToolTip
private void TextBox_MouseMove(object sender, MouseEventArgs e)
{
// Get textbox.
DataGridTextBox hitBox = sender as DataGridTextBox;
if (hitBox != null)
{
// Set ToolTip to textbox's text or, if textbox is empty, to
// null indicator.
string tipText = hitBox.Text == null ? "(null)" : hitBox.Text;
toolTipTest.SetToolTip(hitBox, tipText);
}
}
显示正在编辑的 DataGridBoolColumn 单元格的 ToolTip
对于 DataGridBoolColumn
单元格,在单元格正在编辑时,让 ToolTip
与显示的复选框保持同步更加困难。尽管单元格中看起来有一个 CheckBox
控件,但这只是绘制的。一种解决方法是使用 DataGrid
的 MouseUp
事件切换到同一行中的另一个单元格。这将产生一个建议的 DataRowVersion
,可用于获取要在 ToolTip
中显示的信息。请注意,此方法仅在 DataGrid
中有多列时才有效。如果您的 DataGrid
只有一列,则需要尝试 替代方法之一。
private void GridTest_MouseUp(object sender, MouseEventArgs e)
{
// Get info to determine which cell to inspect.
DataGrid.HitTestInfo hitInfo = gridTest.HitTest(new Point(e.X, e.Y));
CurrencyManager hitManager = (CurrencyManager)
this.BindingContext[gridTest.DataSource, gridTest.DataMember];
// If current target is valid cell, display contents in ToolTip.
if (hitInfo.Row < hitManager.List.Count &&
hitInfo.Type == DataGrid.HitTestType.Cell)
{
// Use CurrencyManager to get DataRowView corresponding to data
// source's row.
DataRowView view = ((DataView)hitManager.List)[hitInfo.Row];
if (view.Row.Table.Columns[hitInfo.Column].DataType == typeof(bool))
{
// Current target is in bool column. Keep track of current cell.
DataGridCell cell = gridTest.CurrentCell;
// Set direction of column change, depending on whether current
// column is last one in row.
int columnChange =
view.Row.Table.Columns.Count == cell.ColumnNumber + 1 ? -1 : 1;
// Move to another column to create proposed DataRowVersion, then back
// again so that user is still in same cell.
gridTest.CurrentCell =
new DataGridCell(cell.RowNumber, cell.ColumnNumber + columnChange);
gridTest.CurrentCell = cell;
// If move caused proposed version to be created, get cell information
// from proposed version.
if (view.Row.HasVersion(DataRowVersion.Proposed))
{
// Set ToolTip to proposed version or, if proposed version is
// empty, to null indicator.
string tipText =
view.Row.IsNull(view.Row.Table.Columns[hitInfo.Column],
DataRowVersion.Proposed) ? "(null)" :
view.Row[hitInfo.Column, DataRowVersion.Proposed].ToString();
toolTipTest.SetToolTip(gridTest, tipText);
}
}
}
}
DataGridBoolColumn 问题的其他方法
另一种方法是为目标列派生一个新的 DataGridColumnStyle
。有关此方法的示例,请参阅 MSDN。该示例的方法返回底层数据源的当前值,而不是与显示的复选框相对应的值,因此需要额外的努力才能使编辑后的值可用于 ToolTip
。
还有一种方法是为 bool
列指定 DataGridTextBoxColumn
样式,这将导致状态显示为文本而不是复选框。这种方法并不理想,因为用户必须输入“true”或“false”才能更改值,但它确实有不要求切换单元格即可捕获更改的优点。
尊重 DataGridColumnStyle 的 NullText
当明确定义了 DataGridColumnStyles
时,在显示单元格 ToolTips 时,尊重 NullText
设置是有意义的。一种方法是创建一个方法来获取显示文本,并使用它而不是显示硬编码的“ (null)”在上面的 GridTest_MouseMove
和 GridTest_MouseUp
示例中。
private string GetNullStyleInfo(int hitColumn)
{
// Assume for the sake of this example that the DataGridTableStyle is
// GridStyle.
if (GridStyle.GridColumnStyles.Count > hitColumn)
{
// The column has a DataGridColumnStyle. Return the NullText string.
DataGridColumnStyle hitStyle = GridStyle.GridColumnStyles[hitColumn];
return hitStyle.NullText;
}
// No DataGridColumnStyle was found. Return a default null text string.
return "(null)";
}
在上面的 GridTest_MouseMove
和 GridTest_MouseUp
方法中,用对 GetNullStyleInfo(hitColumn)
的调用替换硬编码的“ (null)”。无需修改 TextBox_MouseMove
方法,因为它已经显示了正确的文本(即,DataGridTextBox
的 Text
已经具有正确的文本,并且硬编码的“ (null)”可能永远不会被使用)。
历史
- 12-17-2006:
- 更新了文章,讨论了列样式的 null 文本。
- 11-25-2006:
- 改进了代码并更新了文章。
- 10-21-2005:
- 增加了对各种数据类型和列样式的支持。
- 09-29-2005:
- 初始版本。