Основная идея обработка CellPainting
события DataGridView
и измерить длину строки с помощью TextRenderer.MeasureText
и проверить, если строка длиннее, чем ширина ячейки, нарисовать строку справа от ячейки иначе, нарисовать его на левой стороне ,
Примечание: Обращаем внимание, что выравнивание по правому краю текста не является решением. Если вы используете выравнивание по правому краю, когда текст длинный, например Some long text
, он отобразит Some lo...
, в то время как OP нужно, чтобы текст отображался как long text
или ...ng text
. Операции необходимо сначала указать правильную часть текста. Речь идет не о выравнивании по правому краю.
void 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;
}
}
Левое изображение: Для длинных строк, вы видите в правой части строки в ячейке. Внешний вид короткой струны в норме.
Правильное изображение: Столбец шире, поэтому внешний вид нормальный.
Показаны Ellipsis в начале строки
Но появление как-то сбивает с толку пользователей, и они не знают, какая ячейка имеет больше текста и который один не более текст. В таких случаях, показывая многоточие является действительно полезным и на основе ваших предпочтений, многоточие должно быть показано в начале строки так:
Но проблема рисует строку с многоточием в начале строка.
Существует полезный article, написанный Томасом Полаертом.Я внес некоторые небольшие изменения в класс, который он поделил, чтобы вычислить строку с начальным эллипсисом на основе строки, доступной ширины, шрифта и графического объекта, который будет рисовать строку. Я опубликовал измененный код в конце этого сообщения.
Единственное изменение, которое вы должны сделать просчитывает текст с многоточием:
var text = string.Format("{0}", e.FormattedValue);
text = AutoEllipsis.Ellipsis.Compact(text, e.Graphics, e.CellBounds.Width,
e.CellStyle.Font, AutoEllipsis.EllipsisFormat.Start);
Остальная часть кода нетронутым, и результат будет строка с многоточием в начале, несмотря на поведение по умолчанию, который показывает эллипсис в конце.
AutoEllipsis
Исходный код основан на Control
. Я изменил его немного, чтобы передать Graphics
объект, Font
и Width
, который мы хотим использовать для вычисления авто ellipis:
using 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;
}
}
}
Возможный дубликат (HTTP [Как я могу прямо выровнять текст в колонке DataGridView?]://stackoverflow.com/questions/5230316/how-can-i-right-align-text-in-a-datagridview-column) – Luke
@Luke выравнивание по правому краю текста не является решением. Когда текст длинный, например 'Some long text', он отобразит' Some lo ... ', в то время как OP нужно, чтобы текст отображался как' long text' или '... ng text'. Операции необходимо сначала указать правильную часть текста. Речь идет не о выравнивании по правому краю. Взгляните на скриншоты в моем ответе. –
@RezaAghaei Как вы, наверное, можете себе представить, что я сам прочитал этот вопрос, поэтому не было причин его цитировать. Я также не тестировал его, поэтому в этом комментарии есть вопросительный знак. Подумайте об этом таким образом; По умолчанию Text Align = Left, поэтому он сначала отображает левую часть (помимо остальных назначений). Итак, почему бы вам не дать правильное выравнивание, попробуйте также сначала показать правую часть? Не говорите, что это должно сработать, просто говоря, что вы должны попробовать, прежде чем обращаться с самим пациентом. – Luke