DataGridView TextBox列 - 文本很长时显示文本的右侧部分

时间:2016-08-30 21:10:39

标签: c# .net winforms datagridview ellipsis

我在Windows窗体中有一个DataGridView,其中有一列我不想将其设置为适合所有文字的自动尺寸。

相反,我希望在文本很长时显示文本的正确部分。这可能吗?

例如:

  • 单元格的文字为:Some long text

  • 目前宽度只显示:Some long

  • 我希望它首先显示最正文的部分:long text

然后,要查看整个文本,用户可以调整列宽。它与默认行为相反。在默认行为中,它在字符串末尾显示带有省略号的文本的左侧部分,并且要查看右侧部分用户必须更改列宽。

由于

1 个答案:

答案 0 :(得分:3)

主要思想是处理DataGridView TextRenderer.MeasureText事件并使用Some long text测量字符串长度并检查字符串是否长于单元格宽度,否则在单元格右侧绘制字符串,在左侧画出。

注意:请注意,右对齐文字不是解决方案。如果您使用右对齐,当文字很长时(例如Some lo...),它会显示long text,而OP需要将文字显示为...ng textvoid dataGridView1_CellPainting(object sender, DataGridViewCellPaintingEventArgs e) { if (e.RowIndex >= 0 && e.ColumnIndex == 1) { var rect = e.CellBounds; rect.Inflate(-1, 0); e.Paint(e.CellBounds, DataGridViewPaintParts.All & ~(DataGridViewPaintParts.ContentForeground)); var text = string.Format("{0}", e.FormattedValue); var size = TextRenderer.MeasureText(text, e.CellStyle.Font); var flags = TextFormatFlags.Left; if (size.Width > rect.Width) flags = TextFormatFlags.Right; TextRenderer.DrawText(e.Graphics, text, e.CellStyle.Font, rect, e.CellStyle.ForeColor, flags | TextFormatFlags.VerticalCenter); e.Handled = true; } } 。操作需要首先显示正确的文本部分。它不是右对齐。

var text = string.Format("{0}", e.FormattedValue);
text = AutoEllipsis.Ellipsis.Compact(text, e.Graphics, e.CellBounds.Width,
    e.CellStyle.Font, AutoEllipsis.EllipsisFormat.Start);

左图:对于长字符串,您会在单元格中看到字符串的右侧部分。短串外观是正常的。

右图:列更宽,因此外观正常。

CellPainting enter image description here

在字符串开头显示省略号

但是外观在某种程度上让用户感到困惑,他们不知道哪个单元格有更多文本,哪个单元格没有更多文本。在这种情况下,显示省略号非常有用,并且根据您的偏好,省略号应该以这种方式显示在字符串的开头:

enter image description here

但问题是在字符串的开头画一个带省略号的字符串。

Thomas Polaert撰写了一篇有用的enter image description here。我对他分享的类进行了一些小改动,根据字符串,可用宽度,绘制字符串的字体和图形对象计算带有开始省略号的字符串。我在本文末尾发布了更改后的代码。

您需要做的唯一更改是使用省略号计算文本:

Control

其余的代码是不受影响的,结果将是一个开头用省略号的字符串,尽管默认行为在结尾显示省略号。

<强> AutoEllipsis

原始代码依赖于Graphics。我稍微更改了一下以通过我们想要用来计算自动椭圆的Font对象,Widthusing System; using System.Drawing; using System.IO; using System.Text.RegularExpressions; using System.Windows.Forms; namespace AutoEllipsis { /// <summary> /// Specifies ellipsis format and alignment. /// </summary> [Flags] public enum EllipsisFormat { /// <summary> /// Text is not modified. /// </summary> None = 0, /// <summary> /// Text is trimmed at the end of the string. An ellipsis (...) is drawn in place of remaining text. /// </summary> End = 1, /// <summary> /// Text is trimmed at the begining of the string. An ellipsis (...) is drawn in place of remaining text. /// </summary> Start = 2, /// <summary> /// Text is trimmed in the middle of the string. An ellipsis (...) is drawn in place of remaining text. /// </summary> Middle = 3, /// <summary> /// Preserve as much as possible of the drive and filename information. Must be combined with alignment information. /// </summary> Path = 4, /// <summary> /// Text is trimmed at a word boundary. Must be combined with alignment information. /// </summary> Word = 8 } public class Ellipsis { /// <summary> /// String used as a place holder for trimmed text. /// </summary> public static readonly string EllipsisChars = "..."; private static Regex prevWord = new Regex(@"\W*\w*$"); private static Regex nextWord = new Regex(@"\w*\W*"); /// <summary> /// Truncates a text string to fit within a given control width by replacing trimmed text with ellipses. /// </summary> /// <param name="text">String to be trimmed.</param> /// <param name="ctrl">text must fit within ctrl width. /// The ctrl's Font is used to measure the text string.</param> /// <param name="options">Format and alignment of ellipsis.</param> /// <returns>This function returns text trimmed to the specified witdh.</returns> public static string Compact(string text, Graphics g, int width, Font font, EllipsisFormat options) { if (string.IsNullOrEmpty(text)) return text; // no aligment information if ((EllipsisFormat.Middle & options) == 0) return text; if (g == null) throw new ArgumentNullException("g"); Size s = TextRenderer.MeasureText(g, text, font); // control is large enough to display the whole text if (s.Width <= width) return text; string pre = ""; string mid = text; string post = ""; bool isPath = (EllipsisFormat.Path & options) != 0; // split path string into <drive><directory><filename> if (isPath) { pre = Path.GetPathRoot(text); mid = Path.GetDirectoryName(text).Substring(pre.Length); post = Path.GetFileName(text); } int len = 0; int seg = mid.Length; string fit = ""; // find the longest string that fits into // the control boundaries using bisection method while (seg > 1) { seg -= seg / 2; int left = len + seg; int right = mid.Length; if (left > right) continue; if ((EllipsisFormat.Middle & options) == EllipsisFormat.Middle) { right -= left / 2; left -= left / 2; } else if ((EllipsisFormat.Start & options) != 0) { right -= left; left = 0; } // trim at a word boundary using regular expressions if ((EllipsisFormat.Word & options) != 0) { if ((EllipsisFormat.End & options) != 0) { left -= prevWord.Match(mid, 0, left).Length; } if ((EllipsisFormat.Start & options) != 0) { right += nextWord.Match(mid, right).Length; } } // build and measure a candidate string with ellipsis string tst = mid.Substring(0, left) + EllipsisChars + mid.Substring(right); // restore path with <drive> and <filename> if (isPath) { tst = Path.Combine(Path.Combine(pre, tst), post); } s = TextRenderer.MeasureText(g, tst, font); // candidate string fits into control boundaries, try a longer string // stop when seg <= 1 if (s.Width <= width) { len += seg; fit = tst; } } if (len == 0) // string can't fit into control { // "path" mode is off, just return ellipsis characters if (!isPath) return EllipsisChars; // <drive> and <directory> are empty, return <filename> if (pre.Length == 0 && mid.Length == 0) return post; // measure "C:\...\filename.ext" fit = Path.Combine(Path.Combine(pre, EllipsisChars), post); s = TextRenderer.MeasureText(g, fit, font); // if still not fit then return "...\filename.ext" if (s.Width > width) fit = Path.Combine(EllipsisChars, post); } return fit; } } }

{{1}}