How do I programmatically scroll a winforms datagr

2019-01-12 03:24发布

I'm implementing some drag drop features in one my controls inheriting from a datagridview. Basically I'm dragging a row from somewhere in the DGV and dropping it somewhere else, reordering the rows. I've run into a problem though. If the DGV is too large such that there's a scrollbar, how can I have the DGV scroll up or down while the user is in the middle of a dragdrop?

I know how to get the current mouse position and also get the position of the dgv rectangle and such. So, I can easily find out if i'm in the top or bottom half of the rectangle... I just need a way to programmatically scroll the dgv. I'd prefer if I don't have to keep changing the selected cell to do this.

Any suggestions?

Thanks

Isaac

5条回答
我想做一个坏孩纸
2楼-- · 2019-01-12 03:46
dgv.FirstDisplayedScrollingRowIndex = dgv.RowCount - 1;
查看更多
我欲成王,谁敢阻挡
3楼-- · 2019-01-12 03:59

you can do this by setting HorizontalScrollingOffset / VerticalScrollingOffset of the DataGridView

to set HorizontalScrollingOffset

dataGridView1.HorizontalScrollingOffset = dataGridView1.HorizontalScrollingOffset + 10;

check

DataGridView.HorizontalScrollingOffset Property

and

for VerticalScrollingOffset you can use Reflection

include namespace System.Reflection

PropertyInfo verticalOffset = dataGridView1.GetType().GetProperty("VerticalOffset", BindingFlags.NonPublic | BindingFlags.Instance);
            verticalOffset.SetValue(this.dataGridView1, 10, null); 
查看更多
欢心
4楼-- · 2019-01-12 03:59

You need to implement the DragOver event. Check if the mouse is located close to the top or the bottom of the control (use PointToClient). When it is, enable a timer with an interval of ~200 msec. In the Tick event handler scroll the DGV by a row. Disable the timer when the mouse isn't close and after DoDragDrop returns. The user can now easily and intuitively scroll the grid just be hovering near the ends.

查看更多
萌系小妹纸
5楼-- · 2019-01-12 04:01

Well, since this is a datagridview... Sorry for the 'winforms' in the question... but I could just do this.. scrolling up or down one row.

Scroll up:

this.FirstDisplayedScrollingRowIndex = this.FirstDisplayedScrollingRowIndex - 1

Scroll Down:

this.FirstDisplayedScrollingRowIndex = this.FirstDisplayedScrollingRowIndex + 1;

You've gotta make sure to check that the numbers don't go out of bounds though.

查看更多
6楼-- · 2019-01-12 04:02

You may do that using WinAPI by sending message to the control telling it to scroll up or down.

Here is the code, I hope it helps:

private const int WM_SCROLL = 276; // Horizontal scroll
private const int WM_VSCROLL = 277; // Vertical scroll
private const int SB_LINEUP = 0; // Scrolls one line up
private const int SB_LINELEFT = 0;// Scrolls one cell left
private const int SB_LINEDOWN = 1; // Scrolls one line down
private const int SB_LINERIGHT = 1;// Scrolls one cell right
private const int SB_PAGEUP = 2; // Scrolls one page up
private const int SB_PAGELEFT = 2;// Scrolls one page left
private const int SB_PAGEDOWN = 3; // Scrolls one page down
private const int SB_PAGERIGTH = 3; // Scrolls one page right
private const int SB_PAGETOP = 6; // Scrolls to the upper left
private const int SB_LEFT = 6; // Scrolls to the left
private const int SB_PAGEBOTTOM = 7; // Scrolls to the upper right
private const int SB_RIGHT = 7; // Scrolls to the right
private const int SB_ENDSCROLL = 8; // Ends scroll

[DllImport("user32.dll",CharSet=CharSet.Auto)]
private static extern int SendMessage(IntPtr hWnd, int wMsg,IntPtr wParam, IntPtr lParam);

Now assuming you have a textbox control on your form. You can move it with:

SendMessage(textBox1.Handle,WM_VSCROLL,(IntPtr)SB_PAGEUP,IntPtr.Zero); //ScrollUp
SendMessage(textBox1.Handle,WM_VSCROLL,(IntPtr)SB_PAGEDOWN,IntPtr.Zero); //ScrollDown

If that classic general solution doesn't work for you. You may want to look at FirstDisplayedScrollingRowIndex Property and change it regarding your mouse position during dragging.

查看更多
登录 后发表回答