DataGridView垂直滚动条没有正确更新(Forms bug?)

时间:2011-12-26 00:57:03

标签: .net datagridview scrollbar

我在.NET 3.5中遇到过一个错误(我假设)。使用Rows.Add()向DataGridView添加行时,如果禁用DGV,则垂直滚动条无法正确更新。因此,在重新启用DGV后,无法使用滚动条或鼠标滚轮一直滚动到DGV的底部(尽管使用箭头键导航仍然有效。)

所以我正在寻找一种解决方法。有没有办法强制滚动条更新其边界,还是可以手动输入新的最大值?我宁愿不必重新填充DGV。

*)实际上,它是被禁用的父表单,但我认为问题是它传播到DGV控件。

14 个答案:

答案 0 :(得分:20)

这也解决了我的问题:

DataGridView.SuspendLayout();
DataGridView.ResumeLayout();

可以在重新启用DGV之前调用它。


更新: 这也可以完成这项工作:

DataGridView.PerformLayout();

答案 1 :(得分:14)

我刚刚遇到这个问题(我的表单在添加行时被禁用)并通过在添加行之前将网格的滚动条属性设置为“无”来解决它,然后在我的所有行中将其设置回“Both”已被添加。

答案 2 :(得分:2)

我的问题是我的垂直滚动条完全消失了。我对所有上述建议都嗤之以鼻,最后发现让包含DataGridView的面板比表单更窄,解决了问题。在我的情况下,16像素更窄。

答案 3 :(得分:1)

如果没有其他给定的解决方案适合您,我在DataGridView中遇到了与垂直滚动条类似的问题。但问题就是每当行数超出datagridview的高度时,垂直滚动会创建一个混乱的UI。各种行相互重叠。

我有一个数据绑定DataGridView。

这些是我尝试但没有效果的列表。

  1. 将ScrollBars属性设置为None,修改数据源,然后将ScrollBars属性设置为Both。
  2. 以各种组合使用SuspendLayout,ResumeLayout和PerformLayout。
  3. 使用扩展方法为DataGridView设置双缓冲。
  4. 最后,将 AutoSizeRowsMo​​de 设置为 DataGridViewAutoSizeRowsMo​​de.AllCells 为我解决了这个问题。

    如果您在横向滚动方面遇到类似问题,我认为使用 AutoSizeColumnsMode 来解决问题。

答案 4 :(得分:0)

实际上,我刚发现一个解决方法,但我不喜欢它。重新启用DGV后,您可以执行此操作:

int x = Rows.Add();
Rows.RemoveAt(x);

然后更新滚动条。但它不是很漂亮,它会引起一个恼人的小闪烁,它可能引发一些我不得不故意忽略的事件。我会暂时提出这个问题,以期找到更好的解决方案。

答案 5 :(得分:0)

观察到,当DataGridView1的宽度和高度与表单的宽度和高度进行比较时,如果超出表单的尺寸,则重置宽度和高度,滚动条变为可见。

尝试以下代码,它将动态地将DataGridView控件添加到Form并创建一个包含行和列标题名称的方形网格:

  Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
        'Following code adds a Datagridview control to a Form dynamically
        'Step 1.  Add a textbox to a Form, and input the number of columns (ncol). (Note: in this example, ncol=nrow).   
        'Step 2.  Set the Form's Windowstate property to Maximized
        For Each cont As Control In Me.Controls 'remove DataGridView if it already exists on the Form
            If TypeOf (cont) Is DataGridView Then
                Me.Controls.Remove(cont)
            End If
        Next
        Dim DataGridView1 As New DataGridView 'create new data grid view dynamically during run-time
        Me.Controls.Add(DataGridView1) 'add the data grid view to the Form
        Me.Refresh()
        Dim i, nrow, ncol As Integer ' ncol=nrow -->this is a square grid
        ncol = TextBox1.Text
        nrow = ncol 'Note: add a second textbox to the form and input nrow if you don't want a square grid
        DataGridView1.Visible = True
        DataGridView1.Top = 100
        DataGridView1.Left = 100
        DataGridView1.Rows.Clear()
        Do While DataGridView1.Columns.Count > 0
            DataGridView1.Columns.RemoveAt(DataGridView1.Columns.Count - 1)
        Loop
        For i = 1 To ncol
            DataGridView1.Columns.Add(i, "V" & i)
        Next
        DataGridView1.Width = ncol * 115
        DataGridView1.Height = nrow * 22 + 45
        If DataGridView1.Width > Me.Width - DataGridView1.Left Then DataGridView1.Width = Me.Width - DataGridView1.Left - 20
        If DataGridView1.Height > Me.Height - DataGridView1.Top Then DataGridView1.Height = Me.Height - DataGridView1.Top - 50
        DataGridView1.ScrollBars = ScrollBars.None
        For i = 1 To nrow
            DataGridView1.Rows.Add()
            DataGridView1.Rows.Item(i - 1).HeaderCell.Value = "V" & i
        Next
        DataGridView1.AutoResizeRowHeadersWidth(DataGridViewRowHeadersWidthSizeMode.AutoSizeToAllHeaders)
        Dim dgvColumnHeaderStyle As New DataGridViewCellStyle()
        dgvColumnHeaderStyle.Alignment = DataGridViewContentAlignment.MiddleCenter
        DataGridView1.ColumnHeadersDefaultCellStyle = dgvColumnHeaderStyle
        DataGridView1.AllowUserToAddRows = False
        DataGridView1.ScrollBars = ScrollBars.Both
        Me.WindowState = FormWindowState.Maximized
    End Sub

答案 6 :(得分:0)

我想在原帖中添加评论,但我还不能(低于50的声誉)。

我在删除行时遇到了同样的问题。滚动条看起来像禁用,没有滑块可见,箭头是灰色的 将尝试此处描述的变通方法和at this link (explicitly enable the scrollbars again),或者只是保持启用整个DGV 此外,this link suggests the same workaround (explicitly enabling...)并将其称为有效。

答案 7 :(得分:0)

我的问题源于在用户线程中调用dgv.Add()。将其更改为从UI线程调用后,滚动条显示并正常运行:

        if (dataGridView1.InvokeRequired)
        {
            dataGridView1.Invoke((Action)(() => dataGridView1.Rows.Add(new String[] { abc, efg })));
        }
        else
        {
            dataGridView1.Rows.Add(new String[] { calPoint, logUrl });
        }

答案 8 :(得分:0)

由于滑块没有正确调整大小并占用了大部分垂直滚动条,我的解决方案是 -

DGV.height = DGV.Height + 1

DGV.Height = DGV.Height - 1

然后滑块尺寸正确

但我现在使用

DGV.PerformLayout

也解决了这个问题

答案 9 :(得分:0)

我在搜索我遇到的问题时找到了你的帖子。我在Microsoft Surface(Win10)上遇到的是无法使用触摸手势(如轻弹)将DataGridView垂直滚动到长列表的最后一行。通常情况下,最后一行令人抓狂。解决方案很简单,但花了一段时间才弄明白。我将它留在这里以防它有用。

// Override WndProc in your custom class inherited from DataGridView
protected override void WndProc(ref Message m)
{
  switch (m.Msg)
  {
    case 0x115:// WM_VSCROLL
      // The low-order word holds the command
      uint cmd = ((uint)m.WParam & (uint)0x0000FFFF);
      switch (cmd)
      {
        case 5: // SB_THUMBTRACK
          if (Rows.Count > 0)
          {
            // The high-order word holds the position
            uint pos = ((uint)m.WParam & (uint)0xFFFF0000) >> 16;

            // SAVE: This would give us the "true" ratio based on 100%
            // SAVE: double ratio = (double)pos / (double)(VerticalScrollBar.Maximum - VerticalScrollBar.LargeChange);
            // SAVE: Debug.WriteLine("Scroll Position: " + pos + "\t" + (ratio * 100.0).ToString("F2") + "%");

            // What we want is the ratio to the TOP of the thumb, BECAUSE
            // THIS GIVES US THE RATIO TO THE FIRST LINE INDEX
            double firstLineRatio = (double)pos / (double)(VerticalScrollBar.Maximum);
            // We want to make it so that it shows the full line 
            // even if we just barely meet the ratio
            double dFirstLine = firstLineRatio * Rows.Count;
            int iFirstLine = (int)(dFirstLine + 0.9999);
            // SAVE: Debug.WriteLine("Scroll Position: " + pos + "\t" + (ratio * 100.0).ToString("F2") + "%");
            FirstDisplayedScrollingRowIndex = iFirstLine;
            // We do this INSTEAD OF the default for this message, so RETURN
            return;
          }
          break;
      }
      break;
    default:
      break;
  }
  base.WndProc(ref m);
}

答案 10 :(得分:0)

我的解决方案是从其属性中禁用滚动条。 然后在初始化窗口后从代码行启用它们。 DataGridViewObj.ScrollBars = ScrollBars.Both

答案 11 :(得分:0)

对我来说,问题是我将数据网格放在TabPage中,这在数据生成期间没有显示,因此滚动被弄乱了。

我发现只是通过在每次可见更改时自动调整/启用来进行正确的更新:

public MyForm()
{
    InitializeComponent();

    // Automatic scroll to bottom (it might not work if you try to do it without this event)
    datagrid.RowsAdded += (sender, e) =>
    {
        datagrid.FirstDisplayedScrollingRowIndex = datagrid.RowCount - 1;
    };

    // WinForms bug fix: scrollbar update
    datagrid.VisibleChanged += (sender, e) =>
    {
        Enabled = false;
        Enabled = true;
    };
}

答案 12 :(得分:0)

我也有这个问题。似乎与将表格嵌入TabPage中有关。

我依次尝试了所有其他答案。最终对我有用的解决方案是在添加所有行/更新表之后执行以下操作。

mean = df.groupby(['col1', 'col3'])['col2'].mean()

这在我自己修改的DataGridView类中(因此使用“ this”)。您只需替换DataGridView的名称即可。

答案 13 :(得分:-2)

我的DataGridView的最后两行总是隐藏在我的WinForms上。我可以使用键盘向下箭头键滚动到它们(但仍然看不到我实际上在哪一行)。鼠标滚轮和滚动条向下箭头也不会到达它们。只有使用小数据集并最大化表格才能看到最后两行。

以下是我解决问题的方法:我将DataGridView放在Panel中。 BAM!

它还修复了DataGridView的另一个问题,当我调整列标题时,奇怪的垂直线会出现在DataGridView下面的任何UI控件上。这看起来非常丑陋和不专业。但现在它也已修复。