Winforms ListView에서 자동 스크롤 (예 : 상단 또는 하단 근처에 ListView 스크롤)을 구현하려면 어떻게해야합니까? 나는 운 좋은 약으로 구글에서 사냥했다. 나는 이것이 상자 밖으로 작동하지 않습니다 믿을 수 없어!C# 드래그 앤 드롭하는 동안 ListView에서 자동 스크롤 구현
답변
스크롤링은 ListViewItem.EnsureVisible 방법으로 수행 할 수 있습니다. 현재 끌고있는 항목이 목록보기의 보이는 경계에 있고 처음/마지막 항목이 아닌지 판별해야합니다.
private static void RevealMoreItems(object sender, DragEventArgs e)
{
var listView = (ListView)sender;
var point = listView.PointToClient(new Point(e.X, e.Y));
var item = listView.GetItemAt(point.X, point.Y);
if (item == null)
return;
var index = item.Index;
var maxIndex = listView.Items.Count;
var scrollZoneHeight = listView.Font.Height;
if (index > 0 && point.Y < scrollZoneHeight)
{
listView.Items[index - 1].EnsureVisible();
}
else if (index < maxIndex && point.Y > listView.Height - scrollZoneHeight)
{
listView.Items[index + 1].EnsureVisible();
}
}
그런 다음이 메서드를 DragOver 이벤트에 연결합니다.
targetListView.DragOver += RevealMoreItems;
targetListView.DragOver += (sender, e) =>
{
e.Effect = DragDropEffects.Move;
};
감사합니다 링크 (http://www.knowdotnet.com/articles/listviewdragdropscroll.html) 미리 데이브의 덕분에, 전 C#은
class ListViewBase:ListView
{
private Timer tmrLVScroll;
private System.ComponentModel.IContainer components;
private int mintScrollDirection;
[DllImport("user32.dll", CharSet = CharSet.Auto)]
private static extern int SendMessage(IntPtr hWnd, int wMsg, IntPtr wParam, IntPtr lParam);
const int WM_VSCROLL = 277; // Vertical scroll
const int SB_LINEUP = 0; // Scrolls one line up
const int SB_LINEDOWN = 1; // Scrolls one line down
public ListViewBase()
{
InitializeComponent();
}
protected void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
this.tmrLVScroll = new System.Windows.Forms.Timer(this.components);
this.SuspendLayout();
//
// tmrLVScroll
//
this.tmrLVScroll.Tick += new System.EventHandler(this.tmrLVScroll_Tick);
//
// ListViewBase
//
this.DragOver += new System.Windows.Forms.DragEventHandler(this.ListViewBase_DragOver);
this.ResumeLayout(false);
}
protected void ListViewBase_DragOver(object sender, DragEventArgs e)
{
Point position = PointToClient(new Point(e.X, e.Y));
if (position.Y <= (Font.Height/2))
{
// getting close to top, ensure previous item is visible
mintScrollDirection = SB_LINEUP;
tmrLVScroll.Enabled = true;
}else if (position.Y >= ClientSize.Height - Font.Height/2)
{
// getting close to bottom, ensure next item is visible
mintScrollDirection = SB_LINEDOWN;
tmrLVScroll.Enabled = true;
}else{
tmrLVScroll.Enabled = false;
}
}
private void tmrLVScroll_Tick(object sender, EventArgs e)
{
SendMessage(Handle, WM_VSCROLL, (IntPtr)mintScrollDirection, IntPtr.Zero);
}
}
동일한 코드를 사용했지만 그 이유는 무엇입니까? – Ram
George Polevoy의 답변은 –
이 ObjectListView에서보세요에 다루지. 그것은이 일을합니다. 코드를 읽고 ObjectListView 자체를 사용하지 않으려는 경우 사용할 수 있습니다.
미래의 Google 직원을위한 메모 : 더 복잡한 컨트롤 (예 : DataGridView)에서 작동하려면 this thread을 참조하십시오.
보다 훨씬 간단합니다. null이 아닌 항목을 가져 오면 항상 item.EnsureVisible()을 호출 할 수 있습니다. 스크롤이 필요한 경우에는 스크롤을 수행하고 그렇지 않으면 아무 것도 수행하지 않습니다. –
나는 그것을 얻지 않는다. 여기에서 드래그하는 항목 옆에 항목에 대한 InsureVisible 호출이 있습니다. –
item.EnsureVisible()은 해당 항목이 null이 아니고 index, maxIndex, scrollZoneHeight 등을 얻지 않도록 확인한 후에 사용할 수 있습니다. 사용자는 위쪽 또는 아래쪽 가장자리를 약간 드래그해야하지만 작동합니다. 첫 번째 또는 마지막 항목 위로 마우스를 가져 가면 사용자가 코드를 완벽하게 만들 수 있습니다. –