【问题标题】:Show row number in row header of a DataGridView在 DataGridView 的行标题中显示行号
【发布时间】:2012-03-23 19:25:00
【问题描述】:

是否可以在DataGridView 的行标题中显示行号?

我正在尝试使用此代码,但它不起作用:

    private void setRowNumber(DataGridView dgv)
    {
        foreach (DataGridViewRow row in dgv.Rows)
        {
            row.HeaderCell.Value = row.Index + 1;
        }
    }

我必须设置一些DataGridView 属性吗?

【问题讨论】:

    标签: c# .net winforms datagridview


    【解决方案1】:

    您还可以在RowPostPaint 事件中动态绘制字符串:

    private void dgGrid_RowPostPaint(object sender, DataGridViewRowPostPaintEventArgs e)
    {
        var grid = sender as DataGridView;
        var rowIdx = (e.RowIndex + 1).ToString();
    
        var centerFormat = new StringFormat() 
        { 
            // right alignment might actually make more sense for numbers
            Alignment = StringAlignment.Center, 
            LineAlignment = StringAlignment.Center
        };
    
        var headerBounds = new Rectangle(e.RowBounds.Left, e.RowBounds.Top, grid.RowHeadersWidth, e.RowBounds.Height);
        e.Graphics.DrawString(rowIdx, this.Font, SystemBrushes.ControlText, headerBounds, centerFormat);
    }
    

    【讨论】:

    • 谢谢先生!!这对我有用,上面没有任何效果
    • 在对DrawString的调用中不应该是grid.font吗?
    • 性能方面,这优于为每一行设置row.HeaderCell.Value
    • 我只是不明白如何获得这个RowPostPaint 事件?我正在使用WPF,但在我的DataGrid 中没有看到此事件我做错了什么?
    【解决方案2】:

    它似乎没有把它变成一个字符串。 试试看

    row.HeaderCell.Value = String.Format("{0}", row.Index + 1);
    

    【讨论】:

    • 不确定每个人都面临这个问题:我无法在 Form_Load() 之前设置 HeaderCell 的值——即在表单的 CTOR 中。
    【解决方案3】:

    感谢@Gabriel-Perez 和@Groo,好主意!如果其他人需要,这里有一个在 Visual Studio 2012 中测试的 VB 版本。 就我而言,我希望这些数字在行标题中显示为右上角对齐。

    Private Sub MyDGV_RowPostPaint(sender As Object, _
        e As DataGridViewRowPostPaintEventArgs) Handles MyDataGridView.RowPostPaint
    
        ' Automatically maintains a Row Header Index Number 
        '   like the Excel row number, independent of sort order
    
        Dim grid As DataGridView = CType(sender, DataGridView)
        Dim rowIdx As String = (e.RowIndex + 1).ToString()
        Dim rowFont As New System.Drawing.Font("Tahoma", 8.0!, _
            System.Drawing.FontStyle.Bold, _
            System.Drawing.GraphicsUnit.Point, CType(0, Byte))
    
        Dim centerFormat = New StringFormat()
        centerFormat.Alignment = StringAlignment.Far
        centerFormat.LineAlignment = StringAlignment.Near
    
        Dim headerBounds As Rectangle = New Rectangle(_
            e.RowBounds.Left, e.RowBounds.Top, _
            grid.RowHeadersWidth, e.RowBounds.Height)
        e.Graphics.DrawString(rowIdx, rowFont, SystemBrushes.ControlText, _
            headerBounds, centerFormat)
    End Sub
    

    您还可以获得默认字体rowFont = grid.RowHeadersDefaultCellStyle.Font,但它可能看起来不太好。下面的截图使用的是 Tahoma 字体。

    【讨论】:

    • 此选项似乎还具有不自动取消共享行的明显优势(与 row.HeaderCell.Value 相比)。尽管取消共享行在其​​他方面非常容易,但根据Documentation,在可能的情况下为大型数据集保留它们对性能是有利的。
    • 迄今为止的最佳答案。我稍微修改了格式。我更改为 FontStyle.Regular、e.RowBounds.Top+3、e.RowBounds.Height-3 和 SystemBrushes.InactiveCaptionText。现在看起来真的很好。
    • 这不考虑排序。它总是以 1,2,3.... 开头。即使在列排序之后,是否有一个选项可以保留“原始行号”?
    • @JohnGrabanski 那么它不会是行号,而是与该行关联的数据。为此,通常最好添加一列来保存该数据。
    【解决方案4】:
    private void setRowNumber(DataGridView dgv)
    {
        foreach (DataGridViewRow row in dgv.Rows)
        {
            row.HeaderCell.Value = (row.Index + 1).ToString();
        }
    }
    

    这对我有用。

    【讨论】:

      【解决方案5】:

      只是增强了上述解决方案..所以标题它会自行调整其宽度以适应像 12345 这样的长字符串

      private void advancedDataGridView1_RowPostPaint(object sender, DataGridViewRowPostPaintEventArgs e)
      {
          var grid = sender as DataGridView;
          var rowIdx = (e.RowIndex + 1).ToString();
      
          var centerFormat = new StringFormat()
          {
              // right alignment might actually make more sense for numbers
              Alignment = StringAlignment.Center,
      
              LineAlignment = StringAlignment.Center
          };
          //get the size of the string
          Size textSize = TextRenderer.MeasureText(rowIdx, this.Font);
          //if header width lower then string width then resize
          if (grid.RowHeadersWidth < textSize.Width + 40)
          {
              grid.RowHeadersWidth = textSize.Width + 40;
          }
          var headerBounds = new Rectangle(e.RowBounds.Left, e.RowBounds.Top, grid.RowHeadersWidth, e.RowBounds.Height);
          e.Graphics.DrawString(rowIdx, this.Font, SystemBrushes.ControlText, headerBounds, centerFormat);
      }
      

      【讨论】:

        【解决方案6】:

        你可以这样做:

        private void setRowNumber(DataGridView dgv)
        {
            foreach (DataGridViewRow row in dgv.Rows)
            {
                row.HeaderCell.Value = row.Index + 1;
            }
        
            dgv.AutoResizeRowHeadersWidth(DataGridViewRowHeadersWidthSizeMode.AutoSizeToAllHeaders);
        
        }
        

        【讨论】:

          【解决方案7】:

          row.HeaderCell.Value = row.Index + 1;

          当应用于具有大量行的 datagridview 时,会产生内存泄漏,最终会导致内存不足的问题。任何想法如何回收内存?

          以下是适用于包含一些列的空网格的示例代码。它只是在索引中添加行和编号。重复按钮点击几次。

          public partial class Form1 : Form
          {
              public Form1()
              {
                  InitializeComponent();
          
                  dataGridView1.SuspendLayout();
                  for (int i = 1; i < 10000; i++)
                  {
                      dataGridView1.Rows.Add(i);                
                  }
                  dataGridView1.ResumeLayout();
              }
          
              private void button1_Click(object sender, EventArgs e)
              {
                  foreach (DataGridViewRow row in dataGridView1.Rows)
                      row.HeaderCell.Value = (row.Index + 1).ToString();
              }
          }
          

          【讨论】:

          【解决方案8】:

          基于此视频:VB.net-Auto generate row number to datagridview in windows application-winforms,您可以设置 DataSource,此代码放置行号,就像一个魅力。

          private void DataGrid_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
          {
              // Add row number
              (sender as DataGridView).Rows[e.RowIndex].HeaderCell.Value = (e.RowIndex+1).ToString();
          }
          

          【讨论】:

            【解决方案9】:

            这对我有用。

            Private Sub GridView1_CellFormatting(sender As Object, e As DataGridViewCellFormattingEventArgs) Handles GridView1.CellFormatting
                Dim idx As Integer = e.RowIndex
                Dim row As DataGridViewRow = VDataGridView1.Rows(idx)
                Dim newNo As Long = idx
                If Not _RowNumberStartFromZero Then
                    newNo += 1
                End If
            
                Dim oldNo As Long = -1
                If row.HeaderCell.Value IsNot Nothing Then
                    If IsNumeric(row.HeaderCell.Value) Then
                        oldNo = CLng(row.HeaderCell.Value)
                    End If
                End If
            
                If newNo <> oldNo Then 'only change if it's wrong or not set
                    row.HeaderCell.Value = newNo.ToString()
                    row.HeaderCell.Style.Alignment = DataGridViewContentAlignment.MiddleRight
                End If
            End Sub
            

            【讨论】:

            • 你能像问题中那样在 C# 中显示这个吗?
            【解决方案10】:
            private void ShowRowNumber(DataGridView dataGridView)
            {
               dataGridView.RowHeadersWidth = 50;
               for (int i = 0; i < dataGridView.Rows.Count; i++)
               {
                    dataGridView.Rows[i].HeaderCell.Value = (i + 1).ToString();
               }
            }
            

            【讨论】:

              【解决方案11】:

              C# 中的这项工作:

              private void dataGridView1_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
              {
                  int idx = e.RowIndex;
                  DataGridViewRow row = dataGridView1.Rows[idx];
                  long newNo = idx;
                  if (!_RowNumberStartFromZero)
                      newNo += 1;
              
                  long oldNo = -1;
                  if (row.HeaderCell.Value != null)
                  {
                      if (IsNumeric(row.HeaderCell.Value))
                      {
                          oldNo = System.Convert.ToInt64(row.HeaderCell.Value);
                      }
                  }
              
                  if (newNo != oldNo)
                  {
                      row.HeaderCell.Value = newNo.ToString();
                      row.HeaderCell.Style.Alignment = DataGridViewContentAlignment.MiddleRight;
                  }
              }
              

              【讨论】:

                【解决方案12】:
                Private Sub DataGridView1_RowPostPaint(sender As Object, e As DataGridViewRowPostPaintEventArgs) Handles DataGridView1.RowPostPaint
                        Dim rowIdx = (e.RowIndex + 1).ToString()
                        Dim centerFormat = New StringFormat With {.Alignment = StringAlignment.Center, .LineAlignment = StringAlignment.Center}
                        Dim textSize As Size = TextRenderer.MeasureText(rowIdx, sender.Font)
                        If (sender.RowHeadersWidth < textSize.Width + 35) Then
                            sender.RowHeadersWidth = textSize.Width + 35
                        End If
                        Dim headerBounds = New Rectangle(e.RowBounds.Left, e.RowBounds.Top, sender.RowHeadersWidth, e.RowBounds.Height)
                        e.Graphics.DrawString(rowIdx, sender.Font, SystemBrushes.ControlText, headerBounds, centerFormat)
                End Sub
                

                【讨论】:

                • 您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center
                猜你喜欢
                • 2015-05-21
                • 1970-01-01
                • 2010-11-19
                • 2010-11-11
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多