2016-08-30 8 views
1

У меня есть DataGridView в виде окон, в котором есть столбец, который я не хочу, чтобы он был автоматически задан для соответствия всем текстам.DataGridView TextBox Column - Показать правую часть текста, когда текст длинный

Вместо этого я хочу отобразить правую часть текста, когда текст длинный. Это возможно?

Например:

  • Текст для ячейки: Some long text

  • В настоящее время ширина такова, что только это показывает: Some long

  • Я хотел бы, чтобы показать право наиболее часть текста поначалу: long text

Затем, чтобы просмотреть весь текст, пользователь может изменить размер столбца. Это противоположно поведению по умолчанию. В поведении по умолчанию он показывает левую часть текста с эллипсисом в конце строки, а для просмотра правой части пользователь должен изменить ширину столбца.

Благодаря

+0

Возможный дубликат (HTTP [Как я могу прямо выровнять текст в колонке DataGridView?]://stackoverflow.com/questions/5230316/how-can-i-right-align-text-in-a-datagridview-column) – Luke

+0

@Luke выравнивание по правому краю текста не является решением. Когда текст длинный, например 'Some long text', он отобразит' Some lo ... ', в то время как OP нужно, чтобы текст отображался как' long text' или '... ng text'. Операции необходимо сначала указать правильную часть текста. Речь идет не о выравнивании по правому краю. Взгляните на скриншоты в моем ответе. –

+0

@RezaAghaei Как вы, наверное, можете себе представить, что я сам прочитал этот вопрос, поэтому не было причин его цитировать. Я также не тестировал его, поэтому в этом комментарии есть вопросительный знак. Подумайте об этом таким образом; По умолчанию Text Align = Left, поэтому он сначала отображает левую часть (помимо остальных назначений). Итак, почему бы вам не дать правильное выравнивание, попробуйте также сначала показать правую часть? Не говорите, что это должно сработать, просто говоря, что вы должны попробовать, прежде чем обращаться с самим пациентом. – Luke

ответ

3

Основная идея обработка 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; 
    } 
} 

Левое изображение: Для длинных строк, вы видите в правой части строки в ячейке. Внешний вид короткой струны в норме.

Правильное изображение: Столбец шире, поэтому внешний вид нормальный.

enter image description here enter image description here

Показаны Ellipsis в начале строки

Но появление как-то сбивает с толку пользователей, и они не знают, какая ячейка имеет больше текста и который один не более текст. В таких случаях, показывая многоточие является действительно полезным и на основе ваших предпочтений, многоточие должно быть показано в начале строки так:

enter image description here

Но проблема рисует строку с многоточием в начале строка.

Существует полезный 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; 
     } 
    } 
} 
+0

привет, как-то мой оригинальный вопрос переехал сюда и не может прочитать это. это не то, что я просил .. Я не просил эллипсиса в начале текстового поля. Я попросил scoll показать правильную часть текстового значения, а затем прокрутить влево и увидеть полные данные. это решение не отображает полный текст и не может его просмотреть. – dan

+0

@dan Здравствуйте! Нет проблем, я изменил ваш вопрос до его первоначальных требований. Я думал, что вы не знаете «эллипсис», но вы имеете в виду «многоточие», поэтому я добавил несколько описаний. Теперь вопрос такой же, как и в оригинальной версии, но более ясный. Я также отредактировал ответ для поддержки как с/без эллипсиса. Надеюсь, вы сочтете это полезным :) –

+0

спасибо. не уверен, что вы подразумеваете под эллипсисом, но в любом случае я вижу свой оригинальный вопрос, спасибо. – dan