我工作的新公司在他们的 Winforms 应用程序中使用基础设施控件,我没有这方面的经验。我需要订购一个列表(最好通过拖放)以推断列表中项目的优先级。这可以通过内部 Winforms 控件来完成吗?
谢谢安迪
我工作的新公司在他们的 Winforms 应用程序中使用基础设施控件,我没有这方面的经验。我需要订购一个列表(最好通过拖放)以推断列表中项目的优先级。这可以通过内部 Winforms 控件来完成吗?
谢谢安迪
您可以使用一些控件来完成此操作,尽管它们没有内置此功能。这是一个派生的 UltraWinListView,带有一个 DrawFilter,在移动您可以使用的项目时显示突出显示:
这是 DragListView 的代码:
using Infragistics.Win.UltraWinListView;
using System;
using System.Drawing;
using System.Windows.Forms;
using Infragistics.Shared;
using System.Reflection;
namespace WindowsFormsApplication1
{
public class DragListView : UltraListView
{
private DragListViewDrawFilter m_oDrawFilter = new DragListViewDrawFilter();
// stores a boolean that will determine when the mouse is moved if there is something to drag.
bool allowDrag = false;
// stores the item to drag
UltraListViewItem itemToDrag = null;
// stores the point that the initial mouse down occurred
Point startPoint;
internal UltraListViewItem ItemToDrag
{
get { return this.itemToDrag; }
}
protected override void OnCreateControl()
{
base.OnCreateControl();
if (!this.DesignMode)
{
// Wire up events
this.DragDrop += new System.Windows.Forms.DragEventHandler(DragListView_DragDrop);
this.DragLeave += new EventHandler(DragListView_DragLeave);
this.DragOver += new System.Windows.Forms.DragEventHandler(DragListView_DragOver);
this.MouseDown += new System.Windows.Forms.MouseEventHandler(DragListView_MouseDown);
this.MouseLeave += new EventHandler(DragListView_MouseLeave);
this.MouseMove += new System.Windows.Forms.MouseEventHandler(DragListView_MouseMove);
this.MouseUp += new System.Windows.Forms.MouseEventHandler(DragListView_MouseUp);
this.m_oDrawFilter.Invalidate += new EventHandler(m_oDrawFilter_Invalidate);
// Allow dropping on the control
this.AllowDrop = true;
m_oDrawFilter.DropLineColor = Color.Blue;
m_oDrawFilter.DropLineWidth = 3;
this.DrawFilter = m_oDrawFilter;
}
}
void m_oDrawFilter_Invalidate(object sender, EventArgs e)
{
this.Invalidate();
}
void DragListView_DragDrop(object sender, System.Windows.Forms.DragEventArgs e)
{
// get the item being dropped onto if one exists (The coordinates for this event are screen coordinates so they need to be tranlated to client coordinates)
UltraListViewItem dropTarget = m_oDrawFilter.DropHighlightItem;
// only if we have an item that we are dropping on do we do anything
if (dropTarget != null)
{
// if dropLinePosition is AboveItem, then we will drop the item on the targetItems index
int indexModifier = 0;
if (this.m_oDrawFilter.dropLinePosition == ListViewDropLinePositionEnum.BelowItem)
{
indexModifier = 1; // the index of the dropped item should be one more than the targetItem
}
UltraListViewItem itemToMove = e.Data.GetData(typeof(UltraListViewItem)) as UltraListViewItem;
if (itemToMove != null)
{
// move the item by removing it from the list and reinserting at the index of the dropTarget added to the indexModifier
this.Items.Remove(itemToMove);
this.Items.Insert(dropTarget.Index + indexModifier, itemToMove);
itemToMove.Group = dropTarget.Group;
}
}
this.m_oDrawFilter.SetDropHighlight(null, ListViewDropLinePositionEnum.None);
}
void DragListView_DragLeave(object sender, EventArgs e)
{
// When the mouse goes outside the control, clear the drophighlight.
// Since the DropHighlight is cleared when the mouse is not over a ListViewItem, anyway, this is probably not needed.
// But, just in case the user goes from a ListViewItem directly off the control...
m_oDrawFilter.ClearDropHighlight();
}
void DragListView_DragOver(object sender, System.Windows.Forms.DragEventArgs e)
{
// needed to change the drag drop to allow dropping
e.Effect = DragDropEffects.Move;
Point pointInListView = this.PointToClient(new Point(e.X, e.Y));
UltraListViewItem item = this.ItemFromPoint(pointInListView);
if (item == null)
{
// The Mouse is not over an item, do not allow dropping here
e.Effect = DragDropEffects.None;
// Erase any DropHightlight
m_oDrawFilter.ClearDropHighlight();
}
else
{
e.Effect = DragDropEffects.Move;
m_oDrawFilter.SetDropHighlight(item, pointInListView);
}
// Logic to scroll the WinListView if the cursor is dragged near the top or bottom edge of the control
Point p = pointInListView;
UltraListViewItem lvi = this.ItemFromPoint(p);
if (p.Y < this.Height / 10)
{
Scroll(ScrollEventType.SmallDecrement);
}
if (p.Y > this.Height - (this.Height / 10))
{
Scroll(ScrollEventType.SmallIncrement);
}
}
private void Scroll(ScrollEventType value)
{
Type listViewType = this.GetType();
PropertyInfo scrollManagerProperty = listViewType.GetProperty("ScrollManager", BindingFlags.GetProperty | BindingFlags.NonPublic | BindingFlags.Instance);
Object scrollManager = scrollManagerProperty.GetValue(this, null);
Type scrollManagerType = scrollManager.GetType();
scrollManagerType.InvokeMember("Scroll", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.InvokeMethod, null, scrollManager, new object[] { Orientation.Vertical, value });
}
protected void Scroll(UltraListViewItem lvi, int count)
{
KeyedSubObjectsCollectionBase list = this.Items;
if (lvi.Group != null)
list = lvi.Group.Items;
int index = list.IndexOf(lvi);
if (index >= 0)
index += count;
if (index >= 0 && index < list.Count)
{
UltraListViewItem item = list.GetItem(index) as UltraListViewItem;
if (item != null)
item.BringIntoView();
}
}
void DragListView_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
{
// get the item at the mouse location
UltraListViewItem item = this.ItemFromPoint(new Point(e.X, e.Y));
// if there is an item there, then we have to store for possible drag drop
if (item != null)
{
// store the item
this.itemToDrag = item;
// set the flag so dragging can be done in the mouse move
this.allowDrag = true;
// store the start point
this.startPoint = new Point(e.X, e.Y);
}
}
void DragListView_MouseLeave(object sender, EventArgs e)
{
// if the mouse leaves the control, we will not be beginning a drag drop operation
this.allowDrag = false;
}
void DragListView_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e)
{
// check if we have set the flag for allowing dragging (indicates that the mouse has gone
// down over an element and is still down and a drag drop hasn't yet started)
if (this.allowDrag)
{
Point listViewPoint = new Point(e.X, e.Y);
// check if we have moved a few pixels
if (this.DragDistanceReached(this.startPoint, listViewPoint))
{
// we have moved a vew pixels so we will begin the drag, AllowDrag flag is reset
this.allowDrag = false;
// Start the drag.
this.m_oDrawFilter.SetDropHighlight(this.itemToDrag, listViewPoint);
this.DoDragDrop(this.itemToDrag, DragDropEffects.Move);
}
}
}
void DragListView_MouseUp(object sender, System.Windows.Forms.MouseEventArgs e)
{
// Once the mouse comes up, we no longer want to start a drag operation.
this.allowDrag = false;
}
// determines if the mouse has moved a certain distance.
private bool DragDistanceReached(Point p1, Point p2)
{
// get the x distance
int xDist = Math.Abs(p1.X - p2.X);
// get the y distance
int yDist = Math.Abs(p1.Y - p2.Y);
// get the total distance
double totalDistance = Math.Sqrt(xDist * xDist + yDist * yDist);
// we can drag if totalDistance is greater than three.
return totalDistance > 3;
}
}
}
这是 DragListViewDrawFilter 的代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Infragistics.Win;
using Infragistics.Win.UltraWinListView;
using System.Drawing;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
[System.Flags]
internal enum ListViewDropLinePositionEnum
{
None = 0,
AboveItem = 1,
BelowItem = 2,
}
public class DragListViewDrawFilter : IUIElementDrawFilter
{
private UltraListViewItem dropHighlightItem = null;
internal ListViewDropLinePositionEnum dropLinePosition { get; set; }
public Color DropLineColor { get; set; }
public int DropLineWidth { get; set; }
public UltraListViewItem DropHighlightItem
{
get { return dropHighlightItem; }
set
{
if (!this.dropHighlightItem.Equals(value))
{
this.dropHighlightItem = value;
PositionChanged();
}
}
}
public event System.EventHandler Invalidate;
#region IUIElementDrawFilter Members
public bool DrawElement(DrawPhase drawPhase, ref UIElementDrawParams drawParams)
{
switch (drawPhase)
{
case DrawPhase.AfterDrawElement:
{
// We're in AfterDrawElement. So the only states we are conderned with are Below and Above
// Get the elemnt as an UltraListViewItemElement if it is one.
UltraListViewItemUIElement element = drawParams.Element as UltraListViewItemUIElement;
if (element != null && this.dropLinePosition != ListViewDropLinePositionEnum.None && this.dropHighlightItem == element.Item)
{
// Declare a pen to use for drawing Droplines
using (Pen p = new Pen(this.DropLineColor, this.DropLineWidth))
{
// Get a reference to the Grahpics object we are drawing to.
Graphics g = drawParams.Graphics;
// The left edge of the Dropline
int leftEdge = element.Rect.Left;
// right edge of the drop line
int rightEdge = element.Rect.Right;
int lineVPosition;
if (this.dropLinePosition == ListViewDropLinePositionEnum.BelowItem)
{
// Draw Line below item
lineVPosition = element.Rect.Bottom;
g.DrawLine(p, leftEdge, lineVPosition, rightEdge, lineVPosition);
}
if (this.dropLinePosition == ListViewDropLinePositionEnum.AboveItem)
{
// Draw Line below item
lineVPosition = element.Rect.Top;
g.DrawLine(p, leftEdge, lineVPosition, rightEdge, lineVPosition);
}
}
}
// Draw custom image where the mouse is when dragging.
UltraListViewUIElement listViewElement = drawParams.Element as UltraListViewUIElement;
if (null != listViewElement && this.dropLinePosition != ListViewDropLinePositionEnum.None)
{
DragListView dlv = listViewElement.Control as DragListView;
if (dlv != null && dlv.ItemToDrag != null)
{
Image img = dlv.ItemToDrag.Appearance.Image as Image;
if (img != null)
{
Point cursorPosition = dlv.PointToClient(Cursor.Position);
Rectangle rect = new Rectangle(cursorPosition, new Size(30, 30));
drawParams.Graphics.DrawImage(img, rect);
}
}
}
}
break;
}
return false;
}
public DrawPhase GetPhasesToFilter(ref UIElementDrawParams drawParams)
{
return DrawPhase.AfterDrawElement;
}
#endregion
internal void ClearDropHighlight()
{
this.SetDropHighlight(null, ListViewDropLinePositionEnum.None);
}
internal void SetDropHighlight(UltraListViewItem item, ListViewDropLinePositionEnum dropLinePosition)
{
//Use to store whether there have been any changes in
//DropItem or DropLinePosition
bool IsPositionChanged = false;
if (this.dropHighlightItem == null)
{
IsPositionChanged = !(item == null);
}
else
{
//Check to see if the items are equal and if
//the dropline position are equal
if (this.dropHighlightItem.Equals(item) && (this.dropLinePosition == dropLinePosition))
{
//They are both equal. Nothing has changed.
IsPositionChanged = false;
}
else
{
//One or both have changed
IsPositionChanged = true;
}
}
//Set both properties without calling PositionChanged
this.dropHighlightItem = item;
this.dropLinePosition = dropLinePosition;
//Check to see if the PositionChanged
if (IsPositionChanged)
{
//Position did change.
PositionChanged();
}
}
/// <summary>
/// When the dropItem or DropPosition change, we fire the Invalidate event to let the
/// program know to invalidate the Tree control.
/// This is neccessary since the DrawFilter does not have a reference to the Tree Control (although it probably could)
/// </summary>
private void PositionChanged()
{
// if nobody is listening then just return
//
if (null == this.Invalidate)
return;
EventArgs e = EventArgs.Empty;
this.Invalidate(this, e);
}
internal void SetDropHighlight(UltraListViewItem item, Point pointInListView)
{
// The distance from the edge of the item used to determine whether to
// drop Above, Below
int DistanceFromEdge = item.UIElement.Rect.Height / 2;
// The new DropLinePosition
ListViewDropLinePositionEnum NewDropLinePosition;
// Determine which part of the item the point is in
if (pointInListView.Y <= (item.UIElement.Rect.Top + DistanceFromEdge))
{
// Point is in the top of the oNode
NewDropLinePosition = ListViewDropLinePositionEnum.AboveItem;
}
else
{
NewDropLinePosition = ListViewDropLinePositionEnum.BelowItem;
}
// Now that we have the new DropLinePosition, call the real proc to get things rolling
SetDropHighlight(item, NewDropLinePosition);
}
}
}
请注意,您可能希望将命名空间从 WindowsFormsApplication1 更改为其他名称。