.NET Windows窗体编程时加入DataGridView的单元格文本消失窗体、单元格、文本、NET

2023-09-05 00:16:41 作者:梦里桃花香

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

I am developing a Windows forms application that includes a DataGridView. This DataGridView has 3 columns, all of which are simply text cells:

时间戳 连接 消息 Timestamp Connection Message

我遇到的问题是,当我添加行(编程),我发现,如果太长的文字消失。具体而言,如果文本超出 4563 字符的长度,然后将文本消失。

The issue I'm running into is that when I add a row (programmatically), I'm finding that the text disappears if it is too long. To be specific, if the text exceeds 4563 characters in length, then the text disappears.

我知道 DataGridViewTextBoxColumn 类有一个属性调用 MaxInputLength 可以限制数量的输入的字符。但是,根据该的文档,它不仅影响文本手动输入用户。我,但是,我编程输入该文本。

I know that the DataGridViewTextBoxColumn class has a property call MaxInputLength that can limit the number of characters entered. But according the the Documentation, it only affects text that is input manually by the user. I, however, am inputting this text programmatically.

只是为了确保虽然,我设置该属性非常高的,但是当我通过在 4563 字符的限制消失的文字问题还是出现了。

Just to make sure though, I set this property very high but the disappearing text issue still arises when I pass the 4563 character limit.

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

One thing I have noticed is that the text is still there (i.e. the scroll bar along the bottom can still be scrolled as though the text is still there) but I cannot see the text itself. I can also edit the text.

我可以添加字符,直到在 4563 的限制,但只要我传递的文本消失。如果我preSS退格键,返回到完全的 4563 字符,文本再次出现。

I can add characters until the 4563 limit but as soon as I pass that, the text disappears. If I press backspace to return to exactly 4563 characters, the text reappears.

我开发这个使用.NET 4.0,因为我必须支持Windows XP。

I am developing this using .NET 4.0, since I have to support Windows XP.

推荐答案

下面是简短的答案是可能会令你失望:这是一个错误报告和微软验证,关闭,修复没有足够重要的。有可能是它的多个实例,但自从2011年至少它被称为 DataGridView控件显示空白单元格,如果大的字符串输入和列调整到最大。 解决办法是只限制了细胞宽度的大小,但你可能不尽如人意。

Here's the short answer that will probably disappoint you: It's a reported bug and verified by Microsoft, closed as "Not important enough to fix". There may be more instances of it, but it's been known since at least 2011 DataGridView control shows blank cell if large string is entered and column resized to max. The "workaround" is to just limit the size of the cells width, but for you that may not be satisfactory.

不过,好奇心得到了最好的我,所以我开始寻找到它得更深一些;这是第一个观察值得一提的:

However, curiosity got the best of me so I started looking into it a little deeper; Here's the first observation worth mentioning:

如果你看一系列照片,你会发现我的默认字体大小/风格和具体数量5460.有什么特别之处5460复制的问题了吗?好了,没有什么特别,只是因为你的性格门槛穿过它ContentBounds和宽度的列通过32767有什么特别之处32767?除了作为默认的 MaxInputLength DataGridViewTextBoxCell ,它是一个符号short或​​Int16的(2 ^ 15的上限-1)。我很怀疑它的问题在这里发生的一个巧合,但不会造成任何与 MaxInputLength 本身。我愿意打赌,你首先在4563个字符注意到这个问题,因为你的字体大小扩展了宽度为32767为好。

If you look at the series of pictures, you'll notice I replicated your problem with the default font size/style and the specific number 5460. What's so special about 5460? Well, nothing in particular, except that as your character threshold crosses it the ContentBounds and Width of the column passes 32767. What's so special about 32767? Other than being the default MaxInputLength of a DataGridViewTextBoxCell, it's the upper limit of a signed short or Int16 (2^15-1). I highly doubt it's a coincidence the issue is occurring here, though not cause of anything to do with MaxInputLength per se. I'd be willing to bet you first noticed the issue at 4563 characters because your font size expanded the width to 32767 as well.

接下来的问题,是为什么呢?我真的不知道。我开始跟随兔子洞和拆卸一些.NET 4.0的DataGridView *库,找出。这是一个pretty的大规模和复杂的控制,我一直无法得出任何明确的结论,但有一点我发现,值得一提的是绝对的最大宽度一列可以假设为65536,无符号的Int16值(2 ^ 16):

The next question, is why? I'm not really sure. I started following the rabbit hole and disassembled some of the .NET 4.0 DataGridView* libraries to find out. It's a pretty massive and complicated control, and I haven't been able to draw any definite conclusions, but one thing I found that's worth noting is the absolute maximum width a column can assume is 65536, the value of an UNsigned Int16 (2^16):

您添加或调整列时看到此检查在许多私有的内部的地方,我测试了它。规模不会大。

You see this check in a lot of private internal places when adding or resizing a column, and I tested it. The size won't go larger

这是具有讽刺意味的​​原因有两个。首先,使用默认设置,你只能显示10922个字符(每个字符六分之六万五千五百三十六像素)一列中,尽管编辑输入长度为32767个字符,并以编程方式随心所欲。

This is ironic for two reasons. For one, using the default settings, you can only display 10922 characters (65536 / 6 pixels per character) in a column despite the editing input length being 32767 characters, and programmatically arbitrary.

二,为什么会这个问题开始突然出现在列最大宽度的签署变种正是最大? Hmmmm。这是完全一个猜测,但我觉得沿着最大值为任何呈现文本设置为常规短的代替unsigned short ... 或类似的规定行的地方的。我有我的 PaintPrivate()方法的怀疑在 DataGridViewTextBoxCell的实现(),所以如果你感觉活泼,也许把显微镜它。你需要一个IL反汇编器看到这个东西,这不是公开暴露出来。具体来说,这部分的code我的怀疑:

Second, why would this issue start cropping up at exactly the max of the signed variant of the columns max width? Hmmmm. This is totally a guess, but I think somewhere along the line the max value for whatever renders the text was set as a regular short instead of an unsigned short... or something along those lines. I have my suspicions of the PaintPrivate() method in the implementation of DataGridViewTextBoxCell(), so if you're feeling frisky, maybe put a microscope to it. You'll need an IL disassembler to see this stuff that's not exposed publicly. Specifically, this part of the code I have suspicions of:

  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; DR使用小屁屁字体,如果要打包字符转换成巨大的细胞