Click here to Skip to main content
15,891,033 members
Articles / Desktop Programming / Windows Forms

Using the FlowLayoutPanel and Reordering with Drag and Drop

Rate me:
Please Sign up or sign in to vote.
4.81/5 (43 votes)
20 Dec 2009CPOL1 min read 129.2K   10.5K   66   16
Using the FlowLayoutPanel and reordering with drag and drop.

Image 1

Introduction

The FlowLayoutPanel control is actually pretty handy from time to time. In this article, I will explain how to enable drag and drop on two controls. I am using a custom progressbar with drag and drop enabled, so this will only show how to drop and reorder controls. As always, there is probably more than one way to solve this, but this is how I did.

Background

Recently, I had to create a custom drawn progressbar and somehow create a list of those with drag and drop functions. After searching the Internet for a while without luck, I decided to write a little helper here once I finished.

Using the Code

To be able to drag controls to the panel, we first have to add the DragEnter event, either by code or in the Designer.

C#
this.flowLayoutPanel1.DragEnter += new DragEventHandler(flowLayoutPanel_DragEnter); 

void flowLayoutPanel_DragEnter(object sender, DragEventArgs e)
{
    e.Effect = DragDropEffects.All;
}

Then, we add the actual drop event and write the code for it. First, I check if I have dragged the control to the same FlowLayoutPanel. If that's the case, I reorder; if not, then I first add the control and then reorder. The reordering is based on which child control I "drop" the new control on.

C#
this.flowLayoutPanel1.DragDrop += new DragEventHandler(flowLayoutPanel_DragDrop); 

void flowLayoutPanel1_DragDrop(object sender, DragEventArgs e)
{
    HarrProgressBar data = (HarrProgressBar)e.Data.GetData(typeof(HarrProgressBar));
    FlowLayoutPanel _destination = (FlowLayoutPanel)sender;
    FlowLayoutPanel _source = (FlowLayoutPanel)data.Parent;

    if (_source != _destination)
    {
        // Add control to panel
        _destination.Controls.Add(data);
        data.Size = new Size(_destination.Width, 50);
        
        // Reorder
        Point p = _destination.PointToClient(new Point(e.X, e.Y));
        var item = _destination.GetChildAtPoint(p);
        int index = _destination.Controls.GetChildIndex(item, false);
        _destination.Controls.SetChildIndex(data, index);

        // Invalidate to paint!
        _destination.Invalidate();
        _source.Invalidate();
    }
    else
    {
        // Just add the control to the new panel.
        // No need to remove from the other panel,
        // this changes the Control.Parent property.
        Point p = _destination.PointToClient(new Point(e.X, e.Y));
        var item = _destination.GetChildAtPoint(p);
        int index = _destination.Controls.GetChildIndex(item, false);
        _destination.Controls.SetChildIndex(data, index);
        _destination.Invalidate();
    }
}

This will move the control from one panel to another. This code will probably need some tuning if you want to drag from a normal Panel to a FlowLayoutPanel.

Points of Interest

I've put DoDragDrop(); in the HarrProgressBar to be able to drag it onto other controls and to minimize code outside the class.

History

  • 2009-12-21 - v1.0 - Article added.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Architect Consid
Sweden Sweden
I have been working with .NET development since 2003, working with backend systems, and both web and desktop applications. I have experience of integrating software with ERP-systems, connecting production environment, and publishing information to various platforms. With this comes very extensive knowledge about windows OS administration, both server and client. I have worked with almost every OS from Microsoft, and a few linux dists in mixed environment, along with several mobile and "Thin client"-solutions. I have experience in configuring and managing webservers, ftpservers, domains and mailservers in a mixed OS environment.

I'm always looking forward to learning and mastering new technologies.

Specialties: .NET development, PLC integration, ERP integration
Development -> C#, ASP.NET MVC, HTML, WCF, WinForms, Silverlight, PHP, VB6
Database -> MSSQL, MySQL, MsAccess
ERP -> Jeeves, JSB, Jeeves eSales
Automation integration -> TwinCAT, Siemens S7
Automation HMI -> Iconics, Beijer, Indusoft
Microsoft products -> Sharepoint, Microsoft Office
OS -> Windows Guru (Server & Client), Linux (Debian/Ubuntu)

Comments and Discussions

 
QuestionCan we have the dragged HarrProgressBar moving with the mouse? Pin
Yossi Cohen14-Aug-23 1:30
Yossi Cohen14-Aug-23 1:30 
QuestionHello, how to dynamically change the text "MainText" Pin
Alex Chikinov23-Mar-20 22:12
Alex Chikinov23-Mar-20 22:12 
QuestionCustom progress bar for web Application Pin
Member 1270619810-Sep-19 21:14
Member 1270619810-Sep-19 21:14 
QuestionCool Naming Convention Pin
manonthecorner_1-Jul-19 1:05
manonthecorner_1-Jul-19 1:05 
AnswerRe: Cool Naming Convention Pin
Yossi Cohen14-Aug-23 1:26
Yossi Cohen14-Aug-23 1:26 
QuestionHelp with Moving Button Inside FlowLayoutPanel Pin
Member 139004705-Jul-18 16:42
Member 139004705-Jul-18 16:42 
QuestionHELP! Pin
monroed1130-Oct-16 14:58
monroed1130-Oct-16 14:58 
QuestionQuestion Pin
dark-force6-Nov-14 23:05
dark-force6-Nov-14 23:05 
QuestionGreat job.. Pin
indesha369-Mar-14 4:47
indesha369-Mar-14 4:47 
QuestionCatch mouse double click Pin
takar3-Mar-14 1:57
takar3-Mar-14 1:57 
GeneralMy vote of 4 Pin
CodePurveyor23-Aug-13 3:41
CodePurveyor23-Aug-13 3:41 
QuestionClarifying where an item is going to drop. Pin
CodePurveyor23-Aug-13 3:31
CodePurveyor23-Aug-13 3:31 
GeneralMy vote of 5 Pin
Mazen el Senih13-Aug-13 5:58
professionalMazen el Senih13-Aug-13 5:58 
QuestionMy Vote of 5 Pin
Umesh. A Bhat23-Jul-11 0:42
professionalUmesh. A Bhat23-Jul-11 0:42 
NewsSome Errors Fixed. Pin
Pouriya Ghamary4-Feb-11 9:52
Pouriya Ghamary4-Feb-11 9:52 
your HarrProgressBar has some memory leaks. but dont wory new code is here:

---------------HarrProgressBar.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
using Plasmoid.Extensions;
using System.Drawing.Drawing2D;
using System.Diagnostics;
using System.ComponentModel;

namespace Harr
{
    public class HarrProgressBar : Panel
    {

        private Rectangle leftArea;
        private Rectangle statusArea;
        private Rectangle mainArea;
        private Rectangle mainAreaBackground;
        private Rectangle rightArea;
        
        public int RoundedCornerAngle { get; set; }
        public int LeftBarSize { get; set; }
        public int RightBarSize { get; set; }
        public int StatusBarSize { get; set; }
        //public Padding Padding { get; set; }

        //public Font Font { get; set; }
        public string MainText { get; set; }
        public string LeftText { get; set; }
        public string RightText { get; set; }
        public string StatusText { get; set; }

        private Color StatusColor1;
        private Color StatusColor2;
        private int _StatusBarColorIndex;
        /// <summary>
        /// ColorIndex. [0 - Raw active] [1 - Raw inactive] [2 - Dry active] [3 - Dry inactive].
        /// </summary>
        public int StatusBarColor
        {
            get { return _StatusBarColorIndex; }
            set
            {
                switch (value)
                {
                    case 0:
                        // Raw active
                        StatusColor1 = Color.OliveDrab;
                        StatusColor2 = Color.DarkOliveGreen;
                        break;
                    case 1:
                        // Raw inactive
                        StatusColor1 = Color.OliveDrab;
                        StatusColor2 = Color.Gray;
                        break;
                    case 2:
                        // Dry active
                        StatusColor1 = Color.Goldenrod;
                        StatusColor2 = Color.DarkGoldenrod;
                        break;
                    case 3:
                        // Dry inactive
                        StatusColor1 = Color.Goldenrod;
                        StatusColor2 = Color.Gray;
                        break;
                    default:
                        StatusColor1 = Color.DimGray;
                        StatusColor2 = Color.DimGray;
                        break;
                }
            }
        }

        private Color FirstColor;
        private Color SecondColor;
        private int _FillDegree = 50;
        public int FillDegree
        {
            get { return _FillDegree; }
            set 
            {
                if (value >= 100)
                {
                    FirstColor = Color.Red;
                    SecondColor = Color.DarkRed;
                }
                else if (value > 90)
                {
                    FirstColor = Color.Orange;
                    SecondColor = Color.DarkOrange;
                }
                else if (value > 80)
                {
                    FirstColor = Color.Gold;
                    SecondColor = Color.DarkGoldenrod;
                }               
                else
                {
                    FirstColor = Color.Green;
                    SecondColor = Color.DarkGreen;
                }
                _FillDegree = value;
            }
        }

        //Check radius for begin drag n drop
        public bool AllowDrag { get; set; }
        private bool _isDragging = false;
        private int _DDradius = 40;
        private int _mX=0;
        private int _mY=0;

        public HarrProgressBar()
        {
            //Font = new Font("Arial", 10);
            FillDegree = 50;
            RoundedCornerAngle = 10;
            Margin = new Padding(0);
            LeftText = "LT";
            StatusText = "Not set";
            MainText = "MainText";
            RightText = "RT";
            LeftBarSize = 30;
            StatusBarSize = 60;
            RightBarSize = 30;
            StatusBarColor = 99;
            AllowDrag = true;
        }

        protected override void OnResize(EventArgs eventargs)
        {
            base.OnResize(eventargs);
            ReCalcAreas();
        }

        private void ReCalcAreas()
        {
            leftArea = GetLeftArea();
            statusArea = GetStatusArea();
            mainArea = GetMainArea();
            mainAreaBackground = GetMainAreaBackground();
            rightArea = GetRightArea();
        }

        protected override void OnGotFocus(EventArgs e)
        {
            this.BackColor = SystemColors.ActiveCaption;
                //Color.SandyBrown;
            base.OnGotFocus(e);
        }

        protected override void OnLostFocus(EventArgs e)
        {
            this.BackColor = this.FindForm().ContainsFocus ? Color.Transparent : SystemColors.InactiveCaption;
            base.OnLostFocus(e);
        }

        protected override void OnClick(EventArgs e)
        {
            this.Focus();
            base.OnClick(e);
        }

        protected override void OnMouseDown(MouseEventArgs e)
        {
            this.Focus();
            base.OnMouseDown(e);
            _mX = e.X;
            _mY = e.Y;
            this._isDragging = false;
        }

        protected override void OnMouseMove(MouseEventArgs e)
        {
            if (!_isDragging)
            {
                // This is a check to see if the mouse is moving while pressed.
                // Without this, the DragDrop is fired directly when the control is clicked, now you have to drag a few pixels first.
                if (e.Button == MouseButtons.Left && _DDradius > 0 && this.AllowDrag)
                {
                    int num1 = _mX - e.X;
                    int num2 = _mY - e.Y;
                    if (((num1 * num1) + (num2 * num2)) > _DDradius)
                    {
                        DoDragDrop(this, DragDropEffects.All);
                        _isDragging = true;
                        return;
                    }
                }
                base.OnMouseMove(e);
            }
        }

        protected override void OnMouseUp(MouseEventArgs e)
        {
            _isDragging = false;
            base.OnMouseUp(e);
        }

        protected override void OnCreateControl()
        {
            this.SetStyle(ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint
                | ControlStyles.OptimizedDoubleBuffer | ControlStyles.ResizeRedraw
                | ControlStyles.Selectable | ControlStyles.CacheText
                | ControlStyles.SupportsTransparentBackColor, true);

            this.DoubleBuffered = true;
            base.OnCreateControl();
            ReCalcAreas();
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            Graphics g = e.Graphics;

            using (LinearGradientBrush _LeftAndRightBrush = new LinearGradientBrush(mainArea, Color.DimGray, Color.Black, LinearGradientMode.Vertical)
                , _StatusBrush = new LinearGradientBrush(mainArea, StatusColor1, StatusColor2, LinearGradientMode.Vertical)
                , _MainBrush = new LinearGradientBrush(mainArea, FirstColor, SecondColor, LinearGradientMode.Vertical))
            {
                using (StringFormat f = new StringFormat() { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center })
                {
                    // Draw left
                    if (LeftBarSize > 0)
                    {
                        g.FillRoundedRectangle(_LeftAndRightBrush, leftArea, this.RoundedCornerAngle, RectangleEdgeFilter.TopLeft | RectangleEdgeFilter.BottomLeft);
                        g.DrawString(this.LeftText, this.Font, Brushes.White, leftArea, f);
                    }

                    // Draw status
                    if (StatusBarSize > 0)
                    {
                        g.FillRoundedRectangle(_StatusBrush, statusArea, this.RoundedCornerAngle, RectangleEdgeFilter.None);
                        g.DrawString(this.StatusText, this.Font, Brushes.White, statusArea, f);
                    }

                    // Draw main background
                    g.FillRoundedRectangle(Brushes.DimGray, mainAreaBackground, this.RoundedCornerAngle, RectangleEdgeFilter.None);

                    // Draw main
                    g.FillRoundedRectangle(_MainBrush, mainArea, this.RoundedCornerAngle, RectangleEdgeFilter.None);
                    g.DrawString(this.MainText, this.Font, Brushes.White, mainAreaBackground, f);

                    // Draw right
                    if (RightBarSize > 0)
                    {
                        g.FillRoundedRectangle(_LeftAndRightBrush, rightArea, this.RoundedCornerAngle, RectangleEdgeFilter.TopRight | RectangleEdgeFilter.BottomRight);
                        g.DrawString(this.RightText, this.Font, Brushes.White, rightArea, f);
                    }
                }
            }
        }

        private Rectangle GetLeftArea()
        {
            return new Rectangle(
                Padding.Left,
                Padding.Top, 
                LeftBarSize,
                this.ClientRectangle.Height - Padding.Bottom - Padding.Top);
        }

        private Rectangle GetStatusArea()
        {
            return new Rectangle(
                Padding.Left + LeftBarSize,
                Padding.Top,
                StatusBarSize,
                this.ClientRectangle.Height - Padding.Bottom - Padding.Top);
        }

        private Rectangle GetMainArea()
        {
            return new Rectangle(
                Padding.Left + LeftBarSize + StatusBarSize,
                Padding.Top,
                Convert.ToInt32(((this.ClientRectangle.Width - (Padding.Left + LeftBarSize + StatusBarSize + RightBarSize + Padding.Right)) * FillDegree) / 100),
                this.ClientRectangle.Height - Padding.Bottom - Padding.Top);
        }

        private Rectangle GetMainAreaBackground()
        {
            return new Rectangle(
                   Padding.Left + LeftBarSize + StatusBarSize,
                   Padding.Top,
                   this.ClientRectangle.Width - (Padding.Left + LeftBarSize + StatusBarSize + RightBarSize + Padding.Right),
                   this.ClientRectangle.Height - Padding.Bottom - Padding.Top);
        }

        private Rectangle GetRightArea()
        {
            return new Rectangle(
                this.ClientRectangle.Width - (RightBarSize + Padding.Right),
                Padding.Top, 
                RightBarSize,
                this.ClientRectangle.Height - Padding.Bottom - Padding.Top);
        }
    }
}

Generalo my god, wonderful Pin
Pouriya Ghamary2-Feb-11 20:38
Pouriya Ghamary2-Feb-11 20:38 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.