.NET Windows формы DataGridView Текст ячейки исчезает при программном добавлении
Я разрабатываю приложение для форм Windows, которое включает в себя DataGridView
, это DataGridView
имеет 3 столбца, все из которых являются просто текстовыми ячейками:
Timestamp
Connection
Message
Проблема, с которой я сталкиваюсь, заключается в том, что когда я добавляю строку (программно), я обнаруживаю, что текст исчезает, если он слишком длинный. В частности, если длина текста превышает 4563 символа, текст исчезает.
Я знаю что DataGridViewTextBoxColumn
класс имеет вызов свойства MaxInputLength
это может ограничить количество вводимых символов. Но согласно Документации, это влияет только на текст, который вводится пользователем вручную. Я, однако, вводю этот текст программно.
Просто чтобы убедиться, что я установил это свойство очень высоко, но проблема исчезающего текста все еще возникает, когда я превышаю ограничение в 4563 символа.
Одна вещь, которую я заметил, - то, что текст все еще там (то есть полоса прокрутки вдоль основания может все еще быть прокручена, как будто текст все еще там), но я не могу видеть сам текст. Я также могу редактировать текст.
Я могу добавлять символы до предела 4563, но как только я прохожу это, текст исчезает. Если я нажму клавишу Backspace, чтобы вернуться точно к 4563 символам, текст появится снова.
Я разрабатываю это с использованием.NET 4.0, так как я должен поддерживать Windows XP.
1 ответ
Вот краткий ответ, который, вероятно, разочарует вас: это заявленная ошибка, подтвержденная Microsoft и закрытая как "Не достаточно важная, чтобы ее исправить". Может быть больше таких случаев, но это известно, поскольку, по крайней мере, в 2011 году элемент управления DataGridView показывает пустую ячейку, если введена большая строка и размер столбца увеличен до макс. "Обходной путь" - просто ограничить размер ширины ячеек, но для вас это может быть неудовлетворительным.
Тем не менее, любопытство взяло верх над мной, поэтому я начал изучать его немного глубже; Вот первое замечание, которое стоит упомянуть:
Если вы посмотрите на серию изображений, вы заметите, что я повторил вашу проблему с размером / стилем шрифта по умолчанию и конкретным номером 5460. Что такого особенного в 5460? Ну, ничего особенного, за исключением того, что когда порог вашего персонажа пересекает его, ContentBounds и Width столбца проходят 32767. Что такого особенного в 32767? Кроме того, что по умолчанию MaxInputLength
из DataGridViewTextBoxCell
это верхний предел подписанного шорта или Int16 (2^15-1). Я очень сомневаюсь, что это совпадение, проблема возникает здесь, хотя и не является причиной чего-либо общего с MaxInputLength
как таковой. Готов поспорить, вы впервые заметили проблему в 4563 символа, потому что размер шрифта также увеличил ширину до 32767.
Следующий вопрос, почему? Я не совсем уверен. Я начал следить за кроличьей ношей и разобрал некоторые библиотеки.NET 4.0 DataGridView*, чтобы выяснить это. Это довольно массивный и сложный элемент управления, и я не смог сделать каких-либо определенных выводов, но одну вещь, которую я обнаружил, стоит отметить, что абсолютная максимальная ширина, которую может принять столбец, равна 65536, то есть значение Unsigned Int16 (2^16):
Вы видите эту проверку во многих частных внутренних местах при добавлении или изменении размера столбца, и я проверил его. Размер не пойдет больше
Это иронично по двум причинам. Например, используя настройки по умолчанию, вы можете отображать только 10922 символа (65536 / 6 пикселей на символ) в столбце, несмотря на то, что длина ввода для редактирования составляет 32767 символов и является произвольной в программном отношении.
Во-вторых, почему эта проблема начинает возникать именно в максимуме подписанного варианта максимальной ширины столбцов? Хммм. Это полностью предположение, но я думаю, что где-то вдоль линии максимальное значение для любого рендеринга текста было установлено как обычное короткое замыкание вместо беззнакового короткого замыкания... или что-то в этом роде. У меня есть подозрения о 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; DR ИСПОЛЬЗУЙТЕ МАЛЕНЬКУЮ ЗАДНЮЮ ШРИФТУ, ЕСЛИ ВЫ ХОТИТЕ УПАКОВАТЬ ПЕРСОНАЖИ В ОГРОМНЫЕ КЛЕТКИ