Question

I have multiple custom controls (it's a button with a label underneath) added to a FLP. I am trying to be able to rearrange the added custom controls by dragging one over another. With some help made it to work with simple buttons but is not working with the custom control.. Another issue, if I use simple buttons is working only if the FLP is on the form but if I put the FLP inside a tabPage in a tabControl is not working anymore.. Why is not working with the custom control and when the FLP is inside a tabControl?

This what I've been trying so far:

public partial class test_frm : Form
{

   FlowLayoutPanel flowLayoutPanel1 = new FlowLayoutPanel();
    private List<Control> _items = new List<Control>();

    public test_frm()
    {
        InitializeComponent();
        flowLayoutPanel1.AllowDrop = true;
        tabControl1.AllowDrop = true;
        flowLayoutPanel1.Dock = DockStyle.Fill;
        this.Controls.Add(flowLayoutPanel1);
        tabPage1.Controls.Add(flowLayoutPanel1);
        flowLayoutPanel1.DragEnter += new DragEventHandler(flowLayoutPanel1_DragEnter);
        flowLayoutPanel1.DragDrop += new DragEventHandler(flowLayoutPanel1_DragDrop);

        //add custom controls
        for (int i = 0; i < 10; i++)
        {
            Button button = new Button();
            Label lbl = new Label();
            CustomControl cst = new CustomControl(button, lbl);

            button.Text = "Button " + i.ToString();
            lbl.Text = "lbl " + i.ToString();
            cst.Name = "Button " + i.ToString();
            this._items.Add(cst);
            flowLayoutPanel1.Controls.Add(cst);
            cst.MouseDown += new MouseEventHandler(button_MouseDown);
        }
    }


    void flowLayoutPanel1_DragDrop(object sender, DragEventArgs e)
    {

        List<Control> controls = new List<Control>(flowLayoutPanel1.Controls.Count); // get a copy of the controls on the FLP

        foreach (Control ctr in flowLayoutPanel1.Controls)
        {
            controls.Add(ctr);
        }

        for (int i = 0; i < controls.Count; i++)
        {
            Point mouse = PointToClient(new Point(e.X, e.Y));
            if (controls[i].Bounds.Contains(mouse.X - flowLayoutPanel1.Left, mouse.Y - flowLayoutPanel1.Top))
            //If the control is dragged to another control inside the FlowLayoutPanel, move the dragged control to that place.
            {
                string name = (string)e.Data.GetData(typeof(string));
                Control drag = flowLayoutPanel1.Controls.Find(name, true)[0];
                Control temp = controls[i];
                controls.RemoveAt(getIndex(drag.Name));
                controls.Insert(i, drag);

                flowLayoutPanel1.Controls.Clear(); //Clear the controls
                for (int j = 0; j < controls.Count; j++)
                {
                    flowLayoutPanel1.Controls.Add(controls[j]); //Readd all the Controls in new order
                }
                break;
            }

        }
    }

    private int getIndex(string name)
    {
        int result = -1;
        for (int i = 0; i < flowLayoutPanel1.Controls.Count; i++)
        {
            if (flowLayoutPanel1.Controls[i].Name == name)
            {
                result = i;
                break;
            }
        }
        return result;
    }

    void flowLayoutPanel1_DragEnter(object sender, DragEventArgs e)
    {
        e.Effect = DragDropEffects.Copy;
    }


    void button_MouseDown(object sender, MouseEventArgs e)
    {
        (sender as CustomControl).DoDragDrop((sender as CustomControl).Name, DragDropEffects.Copy);

    }
}


public class CustomControl : Control
{
    private Button _button;
    private Label _label;


    public CustomControl(Button button, Label label)
    {
        _button = button;
        _label = label;
        button.Width = 64;
        button.Height = 65;
        button.AutoSize = true;
        label.Width = 65;
        button.FlatStyle = FlatStyle.Flat;
        button.AllowDrop = true;
        //button.Margin = new Padding(15, 15, 15, 15);
        button.BackgroundImageLayout = ImageLayout.Stretch;
        Height = button.Height + label.Height;
        Width = 68;

       // Width = Math.Max(button.Width, label.Width);
        Controls.Add(_button);
        _button.Location = new Point(0, 0);
        Controls.Add(_label);
        _label.Location = new Point(0, button.Height);

    }
Was it helpful?

Solution

Working solution:

private void flowLayoutPanel1_DragDrop(object sender, DragEventArgs e)
{
    Control target = new Control();

    target.Parent = sender as Control;

        if (target != null)
        {
            int targetIndex = FindCSTIndex(target.Parent);
            if (targetIndex != -1)
            {
                string cst_ctrl = typeof(CustomControl).FullName;
                if (e.Data.GetDataPresent(cst_ctrl))

                {
                    Button source = new Button();
                    source.Parent = e.Data.GetData(cst_ctrl) as CustomControl;

                    if (targetIndex != -1)
                        this.flowLayoutPanel1.Controls.SetChildIndex(source.Parent, targetIndex);
                }
            }
        }
    }

private int FindCSTIndex(Control cst_ctr)
{
    for (int i = 0; i < this.flowLayoutPanel1.Controls.Count; i++)
    {    
        CustomControl target = this.flowLayoutPanel1.Controls[i] as CustomControl;

        if (cst_ctr.Parent == target)
            return i;
    }
    return -1;
}

private void OnCstMouseMove(object sender, MouseEventArgs e)
{
    if (e.Button == MouseButtons.Left)
    {
        Control cst = sender as Control;
        cst.DoDragDrop(cst.Parent, DragDropEffects.Move);
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top