using System; using System.Collections.Generic; using System.Text; using System.Windows.Forms; using System.Drawing; using System.ComponentModel; using System.Collections; namespace Emao_ListView { public class MyListView : System.Windows.Forms.ListView { #region Private Members private ListViewItem m_previousItem; private bool m_allowReorder; private Color m_lineColor; #endregion #region Public Properties [Category("Behavior")] public bool AllowReorder { get { return m_allowReorder; } set { m_allowReorder = value; } } [Category("Appearance")] public Color LineColor { get { return m_lineColor; } set { m_lineColor = value; } } #endregion #region Protected and Public Methods public MyListView() : base() { this.FullRowSelect = true; this.GridLines = true; this.View = View.Details; m_allowReorder = true; m_lineColor = Color.Red; SetStyle(System.Windows.Forms.ControlStyles.DoubleBuffer | System.Windows.Forms.ControlStyles.OptimizedDoubleBuffer | System.Windows.Forms.ControlStyles.AllPaintingInWmPaint, true); UpdateStyles(); } protected override void OnDragDrop(DragEventArgs drgevent) { if (!m_allowReorder) { base.OnDragDrop(drgevent); return; } // get the currently hovered row that the items will be dragged to Point clientPoint = base.PointToClient(new Point(drgevent.X, drgevent.Y)); ListViewItem hoverItem = base.GetItemAt(clientPoint.X, clientPoint.Y); if (!drgevent.Data.GetDataPresent(typeof(DragItemData).ToString()) || ((DragItemData)drgevent.Data.GetData(typeof(DragItemData).ToString())).ListView == null || ((DragItemData)drgevent.Data.GetData(typeof(DragItemData).ToString())).DragItems.Count == 0) return; // retrieve the drag item data DragItemData data = (DragItemData)drgevent.Data.GetData(typeof(DragItemData).ToString()); if (hoverItem == null) { // the user does not wish to re-order the items, just append to the end for (int i = 0; i < data.DragItems.Count; i++) { ListViewItem newItem = (ListViewItem)data.DragItems[i]; base.Items.Add(newItem); } } else { // the user wishes to re-order the items // get the index of the hover item int hoverIndex = hoverItem.Index; // determine if the items to be dropped are from // this list view. If they are, perform a hack // to increment the hover index so that the items // get moved properly. if (this == data.ListView) { if (hoverIndex > base.SelectedItems[0].Index) hoverIndex++; } // insert the new items into the list view // by inserting the items reversely from the array list for (int i = data.DragItems.Count - 1; i >= 0; i--) { ListViewItem newItem = (ListViewItem)data.DragItems[i]; base.Items.Insert(hoverIndex, newItem); } } // remove all the selected items from the previous list view // if the list view was found if (data.ListView != null) { foreach (ListViewItem itemToRemove in data.ListView.SelectedItems) { data.ListView.Items.Remove(itemToRemove); } } // set the back color of the previous item, then nullify it if (m_previousItem != null) { m_previousItem = null; } this.Invalidate(); // call the base on drag drop to raise the event base.OnDragDrop(drgevent); } protected override void OnDragOver(DragEventArgs drgevent) { if (!m_allowReorder) { base.OnDragOver(drgevent); return; } if (!drgevent.Data.GetDataPresent(typeof(DragItemData).ToString())) { // the item(s) being dragged do not have any data associated drgevent.Effect = DragDropEffects.None; return; } if (base.Items.Count > 0) { // get the currently hovered row that the items will be dragged to Point clientPoint = base.PointToClient(new Point(drgevent.X, drgevent.Y)); ListViewItem hoverItem = base.GetItemAt(clientPoint.X, clientPoint.Y); Graphics g = this.CreateGraphics(); if (hoverItem == null) { //MessageBox.Show(base.GetChildAtPoint(new Point(clientPoint.X, clientPoint.Y)).GetType().ToString()); // no item was found, so no drop should take place drgevent.Effect = DragDropEffects.Move; if (m_previousItem != null) { m_previousItem = null; Invalidate(); } hoverItem = base.Items[base.Items.Count - 1]; if (this.View == View.Details || this.View == View.List) { g.DrawLine(new Pen(m_lineColor, 2), new Point(hoverItem.Bounds.X, hoverItem.Bounds.Y + hoverItem.Bounds.Height), new Point(hoverItem.Bounds.X + this.Bounds.Width, hoverItem.Bounds.Y + hoverItem.Bounds.Height)); g.FillPolygon(new SolidBrush(m_lineColor), new Point[] { new Point(hoverItem.Bounds.X, hoverItem.Bounds.Y + hoverItem.Bounds.Height - 5), new Point(hoverItem.Bounds.X + 5, hoverItem.Bounds.Y + hoverItem.Bounds.Height), new Point(hoverItem.Bounds.X, hoverItem.Bounds.Y + hoverItem.Bounds.Height + 5) }); g.FillPolygon(new SolidBrush(m_lineColor), new Point[] { new Point(this.Bounds.Width - 4, hoverItem.Bounds.Y + hoverItem.Bounds.Height - 5), new Point(this.Bounds.Width - 9, hoverItem.Bounds.Y + hoverItem.Bounds.Height), new Point(this.Bounds.Width - 4, hoverItem.Bounds.Y + hoverItem.Bounds.Height + 5) }); } else { g.DrawLine(new Pen(m_lineColor, 2), new Point(hoverItem.Bounds.X + hoverItem.Bounds.Width, hoverItem.Bounds.Y), new Point(hoverItem.Bounds.X + hoverItem.Bounds.Width, hoverItem.Bounds.Y + hoverItem.Bounds.Height)); g.FillPolygon(new SolidBrush(m_lineColor), new Point[] { new Point(hoverItem.Bounds.X + hoverItem.Bounds.Width - 5, hoverItem.Bounds.Y), new Point(hoverItem.Bounds.X + hoverItem.Bounds.Width + 5, hoverItem.Bounds.Y), new Point(hoverItem.Bounds.X + hoverItem.Bounds.Width, hoverItem.Bounds.Y + 5) }); g.FillPolygon(new SolidBrush(m_lineColor), new Point[] { new Point(hoverItem.Bounds.X + hoverItem.Bounds.Width - 5, hoverItem.Bounds.Y + hoverItem.Bounds.Height), new Point(hoverItem.Bounds.X + hoverItem.Bounds.Width + 5, hoverItem.Bounds.Y + hoverItem.Bounds.Height), new Point(hoverItem.Bounds.X + hoverItem.Bounds.Width, hoverItem.Bounds.Y + hoverItem.Bounds.Height - 5) }); } // call the base OnDragOver event base.OnDragOver(drgevent); return; } // determine if the user is currently hovering over a new // item. If so, set the previous item's back color back // to the default color. if ((m_previousItem != null && m_previousItem != hoverItem) || m_previousItem == null) { this.Invalidate(); } // set the background color of the item being hovered // and assign the previous item to the item being hovered //hoverItem.BackColor = Color.Beige; m_previousItem = hoverItem; if (this.View == View.Details || this.View == View.List) { g.DrawLine(new Pen(m_lineColor, 2), new Point(hoverItem.Bounds.X, hoverItem.Bounds.Y), new Point(hoverItem.Bounds.X + this.Bounds.Width, hoverItem.Bounds.Y)); g.FillPolygon(new SolidBrush(m_lineColor), new Point[] { new Point(hoverItem.Bounds.X, hoverItem.Bounds.Y - 5), new Point(hoverItem.Bounds.X + 5, hoverItem.Bounds.Y), new Point(hoverItem.Bounds.X, hoverItem.Bounds.Y + 5) }); g.FillPolygon(new SolidBrush(m_lineColor), new Point[] { new Point(this.Bounds.Width - 4, hoverItem.Bounds.Y - 5), new Point(this.Bounds.Width - 9, hoverItem.Bounds.Y), new Point(this.Bounds.Width - 4, hoverItem.Bounds.Y + 5) }); } else { g.DrawLine(new Pen(m_lineColor, 2), new Point(hoverItem.Bounds.X, hoverItem.Bounds.Y), new Point(hoverItem.Bounds.X, hoverItem.Bounds.Y + hoverItem.Bounds.Height)); g.FillPolygon(new SolidBrush(m_lineColor), new Point[] { new Point(hoverItem.Bounds.X - 5, hoverItem.Bounds.Y), new Point(hoverItem.Bounds.X + 5, hoverItem.Bounds.Y), new Point(hoverItem.Bounds.X, hoverItem.Bounds.Y + 5) }); g.FillPolygon(new SolidBrush(m_lineColor), new Point[] { new Point(hoverItem.Bounds.X - 5, hoverItem.Bounds.Y + hoverItem.Bounds.Height), new Point(hoverItem.Bounds.X + 5, hoverItem.Bounds.Y + hoverItem.Bounds.Height), new Point(hoverItem.Bounds.X, hoverItem.Bounds.Y + hoverItem.Bounds.Height - 5) }); } // go through each of the selected items, and if any of the // selected items have the same index as the item being // hovered, disable dropping. foreach (ListViewItem itemToMove in base.SelectedItems) { if (itemToMove.Index == hoverItem.Index) { drgevent.Effect = DragDropEffects.None; hoverItem.EnsureVisible(); return; } } // ensure that the hover item is visible hoverItem.EnsureVisible(); } // everything is fine, allow the user to move the items drgevent.Effect = DragDropEffects.Move; // call the base OnDragOver event base.OnDragOver(drgevent); } protected override void OnDragEnter(DragEventArgs drgevent) { if (!m_allowReorder) { base.OnDragEnter(drgevent); return; } if (!drgevent.Data.GetDataPresent(typeof(DragItemData).ToString())) { // the item(s) being dragged do not have any data associated drgevent.Effect = DragDropEffects.None; return; } // everything is fine, allow the user to move the items drgevent.Effect = DragDropEffects.Move; // call the base OnDragEnter event base.OnDragEnter(drgevent); } protected override void OnItemDrag(ItemDragEventArgs e) { if (!m_allowReorder) { base.OnItemDrag(e); return; } // call the DoDragDrop method base.DoDragDrop(GetDataForDragDrop(), DragDropEffects.Move); // call the base OnItemDrag event base.OnItemDrag(e); } protected override void OnLostFocus(EventArgs e) { // reset the selected items background and remove the previous item ResetOutOfRange(); Invalidate(); // call the OnLostFocus event base.OnLostFocus(e); } protected override void OnDragLeave(EventArgs e) { // reset the selected items background and remove the previous item ResetOutOfRange(); Invalidate(); // call the base OnDragLeave event base.OnDragLeave(e); } #endregion #region Private Methods private DragItemData GetDataForDragDrop() { // create a drag item data object that will be used to pass along with the drag and drop DragItemData data = new DragItemData(this); // go through each of the selected items and // add them to the drag items collection // by creating a clone of the list item foreach (ListViewItem item in this.SelectedItems) { data.DragItems.Add(item.Clone()); } return data; } private void ResetOutOfRange() { // determine if the previous item exists, // if it does, reset the background and release // the previous item if (m_previousItem != null) { m_previousItem = null; } } #endregion #region DragItemData Class private class DragItemData { #region Private Members private MyListView m_listView; private ArrayList m_dragItems; #endregion #region Public Properties public MyListView ListView { get { return m_listView; } } public ArrayList DragItems { get { return m_dragItems; } } #endregion #region Public Methods and Implementation public DragItemData(MyListView listView) { m_listView = listView; m_dragItems = new ArrayList(); } #endregion } #endregion } }
改进了一点点的ListView,数据多不会闪。可以拖动行来进行排序了。
以前主要是自己用。就这样了
要启用拖放行,设置一下 AllowRecoder为true即可。另外多行选择=false