2010-04-21 73 views
7

在vs2008中使用winforms。我有一个DataGridView,我想检测垂直滚动条何时可见。我应该注册哪个事件?如何检测DataGridView控件中的垂直滚动条

我正在添加网格最后一列中的每个单元格值的总和,并在DataGridView底部的文本框中显示该值。

即使在滚动条出现之后,我希望此文本框与单元格值保持一致(我已经使它们右对齐,因为它是$$值)。

回答

8

覆盖DGV行为通常是脖子上的巨大痛苦。尽管这很快就会发生。在窗体中添加一个新类并粘贴下面显示的代码。编译。将新控件从工具栏的顶部拖放到表单上。实施ScrollbarVisibleChanged事件。

using System; 
using System.Windows.Forms; 

class MyDgv : DataGridView { 
    public event EventHandler ScrollbarVisibleChanged; 
    public MyDgv() { 
     this.VerticalScrollBar.VisibleChanged += new EventHandler(VerticalScrollBar_VisibleChanged); 
    } 
    public bool VerticalScrollbarVisible { 
     get { return VerticalScrollBar.Visible; } 
    } 
    private void VerticalScrollBar_VisibleChanged(object sender, EventArgs e) { 
     EventHandler handler = ScrollbarVisibleChanged; 
     if (handler != null) handler(this, e); 
    } 
} 
+0

哎哟,这似乎是一个痛苦只是检测时,一列已经被调整出。 – Billy 2010-04-21 19:05:54

+4

@比利:总是一个错误,不能说你为什么需要一些东西。使用DGV的ColumnWidthChanged事件。 – 2010-04-21 19:35:04

0

我觉得there's任何情况下,对于...但你可以在网格可以成长的所有地方的东西尝试这样的:

  • 获取实际的行数网格视图+标题
  • 将该数字乘以每一行的高度
  • 如果结果大于DataGrid的高度,则必须有一个垂直滚动条。
0

自从他回答问题后,我给了汉斯帕斯坦的复选标记......但是,我又找到了解决方案的另一条路线。由于对话框是模态的,因此项目列表将不会从创建时间开始改变。所以我可以调用下面的代码来确保当对话框第一次显示时文本框位于正确的位置。

/// <summary> 
    /// Horizontally shifts the label and text boxes that display the total 
    /// values so that the totals remain aligned with the columns. 
    /// </summary> 
    private void ShiftTotalsDisplay(DataGridView grid, Label firstLabel, 
    TextBox secondTextBox, TextBox thirdTextBox) 
    {   
    //Note if you have a rowheader add the width here also. 
    int nameRightLoc = grid.Location.X +    
     grid.Columns[0].Width; 
    int fpRightLoc = nameRightLoc + 
     grid.Columns[0].DividerWidth + 
     grid.Columns[1].Width; 
    int dlRightLoc = fpRightLoc + 
     grid.Columns[1].DividerWidth + 
     grid.Columns[2].Width; 

    Point loc = firstLabel.Location; 
    loc.X = nameRightLoc - firstLabel.Width - 2; 
    firstLabel.Location = loc; 

    loc = secondTextBox.Location; 
    loc.X = fpRightLoc - secondTextBox.Width - 2; 
    secondTextBox.Location = loc; 

    loc = thirdTextBox.Location; 
    loc.X = dlRightLoc - thirdTextBox.Width - 2; 
    thirdTextBox.Location = loc;   
    } 
20
var vScrollbar = dataGridView1.Controls.OfType<VScrollBar>().First(); 
if (vScrollbar.Visible) 
{ 
} 
+0

谢谢你添加anwser。我目前正在学习Linq,并热爱它提供的力量! – Billy 2011-10-14 15:00:49

+1

这应该是被接受的答案。我现在正在使用这个功能重新调整表单的大小,直到滚动条消失。 – 2013-08-07 20:34:02

0

如果您DGV是在面板内部,那么你可以比较面板和DGV height属性。如果dgv比面板大,那么必须有一个滚动条,对吧?

像:

int panel_height = pnl.Height; 
int dgv_height = (dgv.RowCount + 1) * 24; // You can play around with this 24 according to your cell styles 
if (dgv_height > panel_height) MessageBox.Show("Voila!"); 
0

设置DGV最后一栏的 “AutoSizeMode” 属性设置为 “填充”,并设置文本框的宽度属性等于dgv.Columns [ “lastcolumn”]宽度。

1

除了使用Linq(Adam Butler)之外,您可以遍历控件并注册一个事件处理程序,每次滚动条可见性更改时都会调用该事件处理程序。我实现它的方式和它的作品相当顺利:

private System.Windows.Forms.DataGridView dgCounterValues; 
private Int32 _DataGridViewScrollbarWidth; 

// get vertical scrollbar visibility handler 
foreach (Control c in dgCounterValues.Controls) 
if (c.GetType().ToString().Contains("VScrollBar")) 
{ 
    c.VisibleChanged += c_VisibleChanged; 
} 

在InitializeComponent() 之后做到这一点的地方在处理程序中,做任何你需要响应垂直滚动条的可见性改变的事情。水平滚动条(与HScrollBar控件取代VScrollBar)相同的工作原理:由于滚动

void c_VisibleChanged(object sender, EventArgs e) 
{ 
    VScrollBar vb = sender as VScrollBar; 
    if (vb.Visible) _DataGridViewScrollbarWidth = vb.Width; 
    else _DataGridViewScrollbarWidth = 0; 
} 
+0

适用于那些拥有.Net前Linq版本的用户的有用代码。然而,我会建议'if(c.GetType()。Equals(typeof(VScrollBar)))'比使用'ToString()'更好的相等比较。另外,这个foreach中的'break'声明会使它更好。 – JPProgrammer 2016-02-10 09:57:15