0

我工作的新公司在他们的 Winforms 应用程序中使用基础设施控件,我没有这方面的经验。我需要订购一个列表(最好通过拖放)以推断列表中项目的优先级。这可以通过内部 Winforms 控件来完成吗?

谢谢安迪

4

1 回答 1

1

您可以使用一些控件来完成此操作,尽管它们没有内置此功能。这是一个派生的 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 更改为其他名称。

于 2013-01-22T20:56:47.360 回答