【问题标题】:Ensuring text wraps in a dataGridView column确保文本在 dataGridView 列中换行
【发布时间】:2011-09-13 14:56:19
【问题描述】:

我有带有特定列的 dataGridView。当我在 dataGridView 中编写长文本时,它会显示一个带有省略号的缩短版本,因为该列的宽度不足以显示整个字符串。

| textdsadasda...  |

如果我想dataGridView在下一行显示这个文本,我必须怎么做?

| textdsadasda     |
| dasdasa          |  (continuation of line above)

如何做到这一点?

【问题讨论】:

标签: c# .net datagridview


【解决方案1】:

没有必要通过重新绘制单元格来重新发明轮子。

简单地说:

  • AutoSizeRowsMode 属性设置为AllCells。这允许行高 与任何包装的文本一起增长。
  • 设置DataGridView.DefaultCellStyle.WrapModeDataGridViewTriState.True 将文本换行到单元格中。
  • 最重要的是设置DataGridView.AutoSizeColumnsModeDataGridViewAutoSizeColumnsMode.None 这样列就不会自行调整大小 (因此它们保持在用户指定的宽度)。

之后,如果列中没有足够的空间,文本应该换行到下一行。

【讨论】:

  • 这拯救了我的一天。这也可以通过设计器单击几下进行配置。
  • 这应该是答案。
【解决方案2】:

尝试设置

  • .AutoSizeMode.DisplayedCells
  • AutoSizeRowsMode 设置为AllCells
  • DataGridView.DefaultCellStyle.WrapModeDataGridViewTriState.True

【讨论】:

  • 它只会调整我的列的大小。我的 dataGrid 中的文本是如此之宽以至于最长的文本。但我希望我的柱子有恒重。文本换行
【解决方案3】:

您可以尝试将DataGridView.DefaultCellStyle.WrapMode 设置为DataGridViewTriState.True

【讨论】:

    【解决方案4】:

    可能正在处理单元格绘制事件可以帮助您

    private void dataGridView1_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)
    {
        if (e.Value == null)
            return;
        var s = e.Graphics.MeasureString(e.Value.ToString(), dataGridView1.Font);
        if (s.Width > dataGridView1.Columns[e.ColumnIndex].Width)
        {
            using (
      Brush gridBrush = new SolidBrush(this.dataGridView1.GridColor),
      backColorBrush = new SolidBrush(e.CellStyle.BackColor))
            {
                e.Graphics.FillRectangle(backColorBrush, e.CellBounds);
                e.Graphics.DrawString(e.Value.ToString(), dataGridView1.Font, Brushes.Black, e.CellBounds,StringFormat.GenericDefault);
                dataGridView1.Rows[e.RowIndex].Height = (int)(s.Height * Math.Ceiling( s.Width / dataGridView1.Columns[e.ColumnIndex].Width)) ;
                e.Handled = true;
            }
        }
    }
    

    【讨论】:

      【解决方案5】:

      我发现@DeveloperX answer 非常有用,但有几个小问题:

      1. 如果有多个单元格需要换行,它会导致某些行闪烁
      2. 某些单元格的最后一行缺失或被截断(如果有长词无法包含在文本中,则会发生这种情况)

      它还导致缺少单元格边框(但这取决于网格/单元格边框设置)。

      我对@DeveloperX 代码进行了返工来解决这个问题,并提出了以下代码:

      private int _rowMaxHeight = 0;
      private int _rowDefaultHeight = 0;
      private void dataGridView1_CellPainting(object sender, 
          DataGridViewCellPaintingEventArgs e)
      {
          if (e.Value == null || e.RowIndex < 0)
          {
              // The WordWrap code is ony executed if requested the cell has a value,
              // and if this is not the heading row.
              return;
          }
          if (e.ColumnIndex == 0)
          {
              // Resetting row max height on each row's first cell
              _rowMaxHeight = 0;
              if (_rowDefaultHeight == 0)
              {
                  /* The default DataGridView row height is saved when the first cell
                   * inside the first row is populated the first time. This is later
                   * used as the minimum row height, to avoid 
                   * smaller-than-default rows. */
                  _rowDefaultHeight = dataGridView1.Rows[e.RowIndex].Height;
              }
          }
          // Word wrap code
          var sOriginal = e.Graphics.MeasureString(e.Value.ToString(), 
              dataGridView1.Font);
          var sWrapped = e.Graphics.MeasureString(e.Value.ToString(), 
              dataGridView1.Font,
              // Is is MeasureString that determines the height given the width, so
              // that it properly takes the actual wrapping into account
              dataGridView1.Columns[e.ColumnIndex].Width);    
          if (sOriginal.Width != dataGridView1.Columns[e.ColumnIndex].Width)
          {
              using (Brush gridBrush = new SolidBrush(this.dataGridView1.GridColor), 
                  backColorBrush = new SolidBrush(e.CellStyle.BackColor), 
                  fontBrush = new SolidBrush(e.CellStyle.ForeColor))
              {
                  e.Graphics.FillRectangle(backColorBrush, e.CellBounds);
                  // The DrawLine calls restore the missing borders: which borders
                  // miss and how to paint them depends on border style settings
                  e.Graphics.DrawLine(new Pen(gridBrush, 1),
                      new Point(e.CellBounds.X - 1, 
                          e.CellBounds.Y + e.CellBounds.Height - 1),
                      new Point(e.CellBounds.X + e.CellBounds.Width - 1, 
                          e.CellBounds.Y + e.CellBounds.Height - 1));
                  e.Graphics.DrawLine(new Pen(gridBrush, 1),
                      new Point(e.CellBounds.X + e.CellBounds.Width - 1, 
                          e.CellBounds.Y - 1),
                      new Point(e.CellBounds.X + e.CellBounds.Width - 1, 
                          e.CellBounds.Y + e.CellBounds.Height - 1));
                  //Updating the maximum cell height for wrapped text inside the row:
                  // it will later be set to the row height to avoid the flickering
                  // that would occur by setting the height multiple times.
                  _rowMaxHeight = (Math.Ceiling(sWrapped.Height) > _rowMaxHeight)
                      ? (int)Math.Ceiling(sWrapped.Height) : _rowMaxHeight;
                  // The text is generated inside the row.
                  e.Graphics.DrawString(e.Value.ToString(), dataGridView1.Font, 
                      fontBrush, e.CellBounds, StringFormat.GenericDefault);
                  e.Handled = true;
              }
          }
          if (e.ColumnIndex == dataGridView1.ColumnCount -1 
              && _rowMaxHeight > 0 
              && _rowMaxHeight != dataGridView1.Rows[e.RowIndex].Height)
          {
              // Setting the height only in the last cell, when the full row has been
              // painted, helps to avoid flickering when more than one row 
              // needs the wrap.
              dataGridView1.Rows[e.RowIndex].Height = 
                  (_rowMaxHeight > _rowDefaultHeight) 
                  ? _rowMaxHeight : _rowDefaultHeight;
          }
      }
      

      请注意,这段代码还有一个问题尚未解决:单元格内的文本不再垂直居中!

      【讨论】:

      • 这工作正常,但是当您添加其他类型的列时,此解决方案会忽略这些列类型并绘制文本,而不是按钮列。将 'AutoSizeRowMode' 设置为 'AllCells' 并设置要包装的列和 autohight 'dataGridViewColumn.DefaultCellStyle.WrapMode = DataGridViewTriState.True;'
      【解决方案6】:

      设置此值是否有助于实现所需的显示效果

      dataGridView1.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.DisplayedCells;
      

      除了设置WrapMode = DataGridViewTriState.True;

      【讨论】:

        【解决方案7】:

        我发现 DeveloperX 的回答非常好。但我发现我需要稍微调整一下。首先,我需要确保有问题的列不在 AutoSizeMode 中:

            if (dgv.Columns[e.ColumnIndex].AutoSizeMode != DataGridViewAutoSizeColumnMode.None)
                throw new InvalidOperationException(String.Format("dgv {0} AutoSizeMode <> 'None'", dgv.Columns[e.ColumnIndex].Name));
        

        我还发现使用

        var s = e.Graphics.MeasureString(e.Value.ToString(), dataGridView1.Font);
        

        返回一个字符串长度,不能用于与以像素为单位的 ColumnWidth 进行比较。所以,使用How can I convert a string length to a pixel unit?,我将上面的代码行修改为

        var s = e.Graphics.MeasureString(e.Value.ToString(), new Font("Segoe UI", 11, FontStyle.Regular, GraphicsUnit.Pixel));
        

        我还发现直接比较宽度不足以确定何时防止剪裁 - 有一些边缘情况没有被捕获。所以,我换了

        if (s.Width > dataGridView1.Columns[e.ColumnIndex].Width)
        

        有一个比率比较(通过实验确定的截止值):

        if (e.Value.ToString().Length / (double)dataGridView1.Columns[e.ColumnIndex].Width >= .189)
        

        最后,选中行中的单元格没有高亮显示,所以我添加了以下内容:

               SolidBrush backColorBrush;
                if (dataGridView1.SelectedRows[0].Index == e.RowIndex)
                    backColorBrush = new SolidBrush(e.CellStyle.SelectionBackColor);
                else
                    backColorBrush = new SolidBrush(e.CellStyle.BackColor);
        

        最终代码:

        private void dataGridView1_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)
        {
            if (e.Value == null || e.RowIndex == -1)
                return;
        
            if (dataGridView1.Columns[e.ColumnIndex].AutoSizeMode != DataGridViewAutoSizeColumnMode.None)
                throw new InvalidOperationException(Format("dataGridView1 {0} AutoSizeMode <> 'None'", dataGridView1.Columns[e.ColumnIndex].Name));
        
            var s = e.Graphics.MeasureString(e.Value.ToString(), new Font("Segoe UI", 11, FontStyle.Regular, GraphicsUnit.Pixel));
            if (e.Value.ToString().Length / (double)dataGridView1.Columns[e.ColumnIndex].Width >= .189)
            {
                SolidBrush backColorBrush;
                if (dataGridView1.SelectedRows[0].Index == e.RowIndex)
                    backColorBrush = new SolidBrush(e.CellStyle.SelectionBackColor);
                else
                    backColorBrush = new SolidBrush(e.CellStyle.BackColor);
        
                using (backColorBrush)
                {
                    e.Graphics.FillRectangle(backColorBrush, e.CellBounds);
                    e.Graphics.DrawString(e.Value.ToString(), dataGridView1.Font, Brushes.Black, e.CellBounds, StringFormat.GenericDefault);
                    dataGridView1.Rows[e.RowIndex].Height = System.Convert.ToInt32((s.Height * Math.Ceiling(s.Width / (double)dataGridView1.Columns[e.ColumnIndex].Width)));
                    e.Handled = true;
                }
            }
        }
        

        【讨论】:

          【解决方案8】:

          要进行包装,在绑定后添加这个

          DataGrid1.ItemStyle.Wrap = true;
          

          【讨论】:

            【解决方案9】:

            我同意在单元格上简单地设置WordWrap 的答案,并将添加到这个场景中。

            我需要根据每个单元格中的数据动态更改颜色和字体样式。最初,我认为由于需要不同的文本颜色,我无法弄清楚如何使 DrawStringCellPainting 事件中的包装一起工作。

            但是,最后我只是在CellPainting 事件中设置了Cell.Style 属性,然后在没有设置e.Handled = true 的情况下退出了事件。这样,网格的绘制事件就使用了我为每个单元格设置的样式,并且正确包装了文本。

            例如:

            datagrid1[e.ColumnIndex, e.RowIndex].Style.BackColor = Color.Green;
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多