.NET Windows窗体DataGridView单元格文本在以编程方式添加时消失

时间:2014-03-10 17:39:28

标签: c# .net winforms datagridview

我正在开发一个包含DataGridView的Windows窗体应用程序。这个DataGridView有3列,所有列都只是文本单元格:

  • Timestamp
  • Connection
  • Message

我遇到的问题是,当我添加一行(以编程方式)时,我发现如果文本太长,文本就会消失。具体而言,如果文字长度超过 4563 个字符,则文字会消失。

我知道DataGridViewTextBoxColumn类有一个属性调用MaxInputLength,可以限制输入的字符数。但是根据Documentation,它只会影响用户手动输入的文本。但是,我正在以编程方式输入此文本。

为了确保这一点,我将此属性设置得非常高,但当我通过 4563 字符限制时,仍会出现消失的文本问题。

我注意到的一件事是文本仍然存在(即底部的滚动条仍然可以滚动,就像文本仍在那里一样)但我看不到文本本身。我也可以编辑文本。

我可以添加字符,直到 4563 限制,但一旦我通过,文字就会消失。如果按退格键返回 4563 字符,则会再次显示该文本。

我正在使用.NET 4.0进行开发,因为我必须支持Windows XP。

1 个答案:

答案 0 :(得分:6)

这里的简短回答可能会令您失望:它是一个报告的错误并经Microsoft验证,关闭为"不够重要,无法修复"。可能会有更多的实例,但至少自2011年DataGridView control shows blank cell if large string is entered and column resized to max以来就已为人所知。 "解决方法"只是限制单元格宽度的大小,但对你来说可能不太令人满意。

然而,好奇心得到了我的好处,所以我开始深入研究它;这是第一个值得一提的观察:

enter image description here

如果您查看一系列图片,您会注意到我使用默认字体大小/样式和特定编号5460复制了您的问题。5460的特别之处是什么?好吧,没什么特别的,除了当你的角色阈值越过它时,列的ContentBounds和Width传递32767. 32767的特别之处是什么?除了MaxInputLength的默认DataGridViewTextBoxCell之外,它还是签名短片或Int16(2 ^ 15-1)的上限。我非常怀疑这里发生的问题是巧合,尽管这与MaxInputLength本身没有任何关系。我愿意打赌你首先注意到4563个字符的问题,因为你的字体大小也将宽度扩展到了32767.

接下来的问题是,为什么?我不太确定。我开始关注兔子洞并拆解一些.NET 4.0 DataGridView *库以找出答案。它是一个非常庞大而复杂的控制,我还没有得出任何明确的结论,但有一点我发现值得注意的是列可以假设的绝对最大宽度为65536,一个UNsigned Int16(2 ^ 16)的值:

enter image description here

在添加或调整列时,您会在很多私有内部位置看到此检查,并对其进行了测试。尺寸不会变大

这具有讽刺意味,有两个原因。例如,使用默认设置,尽管编辑输入长度为32767个字符,并且在编程上是任意的,但您只能在列中显示10922个字符(每个字符65536/6像素)。

第二,为什么这个问题会在最大列宽最大值的最大值处开始出现? Hmmmm。这是完全一个猜测,但我认为沿着这条线的某个地方,无论是什么渲染文本被设置为常规短而不是无符号短... 或沿着这些线的东西的最大值。我怀疑PaintPrivate()实施DataGridViewTextBoxCell()方法,所以如果你感觉活泼,可能会把显微镜放在上面。您需要一个IL反汇编程序才能看到这些未公开曝光的内容。具体来说,这部分代码我怀疑:

  if (text != null && (paint && !flag2 || computeContentBounds))
  {
    int y = cellStyle.WrapMode == DataGridViewTriState.True ? 1 : 2;
    rectangle3.Offset(0, y);
    // ISSUE: explicit reference operation
    // ISSUE: variable of a reference type
    Rectangle& local = @rectangle3;
    // ISSUE: explicit reference operation
    int width = (^local).Width;
    // ISSUE: explicit reference operation
    (^local).Width = width;
    rectangle3.Height -= y + 1;
    if (rectangle3.Width > 0 && rectangle3.Height > 0)
    {
      TextFormatFlags cellStyleAlignment = DataGridViewUtilities.ComputeTextFormatFlagsForCellStyleAlignment(this.DataGridView.RightToLeftInternal, cellStyle.Alignment, cellStyle.WrapMode);
      if (paint)
      {
        if (DataGridViewCell.PaintContentForeground(paintParts))
        {
          if ((cellStyleAlignment & TextFormatFlags.SingleLine) != TextFormatFlags.Default)
            cellStyleAlignment |= TextFormatFlags.EndEllipsis;
          TextRenderer.DrawText((IDeviceContext) graphics, text, cellStyle.Font, rectangle3, flag3 ? cellStyle.SelectionForeColor : cellStyle.ForeColor, cellStyleAlignment);
        }
      }
      else
        rectangle1 = DataGridViewUtilities.GetTextBounds(rectangle3, text, cellStyleAlignment, cellStyle);
    }

抱歉这本书!

TL;如果您希望将字符包含在巨大的细胞中,请使用小屁股。