1

What I am attempting to accomplish is to move by drag and drop method a bunch of composite controls as outlined by the following image:

CompositeControl Example

Currently I am able to do this by only the edge of the composite control. Is it even possible to be able to click on a child/daughter control in the composite control to be able to move the entire composite control?

Here is my code for the addition of the control to panel3 of the main form:

private void newPictureBox_Click(object sender, EventArgs e)
{
    UserControl1 _UserControl = new UserControl1();
    PictureBox _PictureBox = (PictureBox)sender;
    string _NewControlClusterName = "_New" + _PictureBox.Name;

    _UserControl.Name = _NewControlClusterName;
    _UserControl.ThreadCount = 16;
    _UserControl.ImageBackground = _PictureBox.BackColor;
    _UserControl.Dock = DockStyle.Top;
    _UserControl.AllowDrop = true;
    _UserControl.Cursor = Cursors.SizeAll;

    _UserControl.MouseMove += _UserControl_MouseMove;
    _UserControl.DragDrop += _UserControl_DragDrop;
    _UserControl.DragEnter += _UserControl_DragEnter;

    string ColorName = toolTip1.GetToolTip(_PictureBox);
    string ColorCode = toolTip2.GetToolTip(_PictureBox);
    toolTip1.SetToolTip(_UserControl.pictureBox1, ColorName);
    toolTip2.SetToolTip(_UserControl.pictureBox1, ColorCode);
    toolTip2.Active = false;

    _UserControl.PictureClick += new EventHandler(ClusterControl_Click);
    _UserControl.TrackBarScroll += new EventHandler(GetTartanCode);

    panel3.Controls.Add(_UserControl);
    panel3.Controls.SetChildIndex(_UserControl, 0);
}

private void _UserControl_DragEnter(object sender, DragEventArgs e)
{
    e.Effect = DragDropEffects.Move;
}

private void _UserControl_DragDrop(object sender, DragEventArgs e)
{
    UserControl1 target = sender as UserControl1;
    if (target != null)
    {
        int targetIndex = FindUserControlIndex(target);
        if (targetIndex != -1)
        {
            string _UserControlFormat = typeof(UserControl1).FullName;
            if (e.Data.GetDataPresent(_UserControlFormat))
            {
                UserControl1 source = e.Data.GetData(_UserControlFormat) as UserControl1;
                int sourceIndex = this.FindUserControlIndex(source);
                if (targetIndex != -1)
                    this.panel3.Controls.SetChildIndex(source, targetIndex);
            }
        }
    }
}

private int FindUserControlIndex(UserControl1 _UserControl)
{
    for (int i = 0; i < this.panel3.Controls.Count; i++)
    {
        UserControl1 target = this.panel3.Controls[i] as UserControl1;
        if (_UserControl == target)
            return i;
    }
    return -1;
}

private void _UserControl_MouseMove(object sender, MouseEventArgs e)
{
    if (e.Button == MouseButtons.Left)
    {
        UserControl1 _UserControl1 = sender as UserControl1;
        _UserControl1.BorderStyle = BorderStyle.Fixed3D;
        _UserControl1.DoDragDrop(_UserControl1, DragDropEffects.All);
    }
}

private void ClusterControl_Click(object sender, EventArgs e)
{
    PictureBox _PictureBox = (PictureBox)sender;
    GroupBox _GroupBox = (GroupBox)_PictureBox.Parent;
    UserControl1 _UserControl1 = (UserControl1)_GroupBox.Parent;
    panel3.Controls.Remove(_UserControl1);
}
John Schultz
  • 672
  • 1
  • 10
  • 29

2 Answers2

2

There is no simple way to do this.

You can try to attach your event handler to every child controls recursively.
Something like this:

public class UserControl1 : Control
{
    public UserControl1()
    {
        // ...
        ApplyChildEvents(this);
    }

    private void ApplyChildEvents(Control control)
    {
        foreach (Control subcontrol in control.Controls)
        {
            subcontrol.MouseMove += _UserControl_MouseMove;
            subcontrol.DragDrop += _UserControl_DragDrop;
            subcontrol.DragEnter += _UserControl_DragEnter;

            ApplyChildEvents(subcontrol);
        }
    }
}

So, all controls on your UserControl1 will call this method.

Yeldar Kurmangaliyev
  • 33,467
  • 12
  • 59
  • 101
  • I understand this part, what I do not understand is, if it is possible to drag the entire control by dragging on a child control of it. For instance, the group box. – John Schultz Nov 04 '15 at 04:41
  • OK, made a chage to the code to reflect dynamic additions for the _USerControl by setting the properties for only the groupbox. Tried to move one of the composite controls by the groupbox and I get a NullReferenceException (Object reference not set to an instance of an object) on `_UserControl1.BorderStyle.Fixed3D;` in the _UserControl_MouseMove event handler. – John Schultz Nov 04 '15 at 08:45
  • @JohnSchultz Remove `sender` usage. `Sender` is of another type. Use current object's propreties. – Yeldar Kurmangaliyev Nov 04 '15 at 08:46
  • I made an addition to the code in that event handler and will post it as an additional answer to yours. Both answers are needed to get this to work. – John Schultz Nov 04 '15 at 08:52
  • Followup question - any chance there is a way to animate the move. I.E. when I grab a control, the ui displays that control as being moved instead of a mouse pointer and a little box under it? – John Schultz Nov 04 '15 at 09:00
  • @JohnSchultz You can do this manually. For example, stop using `DoDragDrop` and `DragDrop` \ `DragEnter` events. Use `MouseDown`, `MouseUp`, `MouseMove`. I guess, that's absolutely another question :) – Yeldar Kurmangaliyev Nov 04 '15 at 09:13
1

Used the answer above along with the following code adjustment to the _UserControl_MouseMove event handler and it now works perfectly.

private void _UserControl_MouseMove(object sender, MouseEventArgs e)
{
    if (e.Button == MouseButtons.Left)
    {
        if (sender.GetType() == typeof(GroupBox))
        {
            GroupBox _GroupBox = sender as GroupBox;
            UserControl1 _UserControl1 = _GroupBox.Parent as UserControl1;
            _UserControl1.BorderStyle = BorderStyle.Fixed3D;
            _UserControl1.DoDragDrop(_UserControl1, DragDropEffects.All);
        }
        else
        {
            UserControl1 _UserControl1 = sender as UserControl1;
            _UserControl1.BorderStyle = BorderStyle.Fixed3D;
            _UserControl1.DoDragDrop(_UserControl1, DragDropEffects.All);
        }
    }
}

And also had to change the above code to the following (since the area mentioned to follow is generated on the fly):

newPictureBox_Click

foreach (Control subcontrol in _UserControl.Controls)
{
    if (subcontrol.GetType() == typeof(GroupBox)){
        subcontrol.MouseMove += _UserControl_MouseMove;
        subcontrol.DragDrop += _UserControl_DragDrop;
        subcontrol.DragEnter += _UserControl_DragEnter;
    }
}

Complete code is as follows:

private void newPictureBox_Click(object sender, EventArgs e)
{
    UserControl1 _UserControl = new UserControl1();
    PictureBox _PictureBox = (PictureBox)sender;
    string _NewControlClusterName = "_New" + _PictureBox.Name;

    _UserControl.Name = _NewControlClusterName;
    _UserControl.ThreadCount = 16;
    _UserControl.ImageBackground = _PictureBox.BackColor;
    _UserControl.Dock = DockStyle.Top;
    _UserControl.AllowDrop = true;
    _UserControl.Cursor = Cursors.SizeAll;

    _UserControl.MouseMove += _UserControl_MouseMove;
    _UserControl.DragDrop += _UserControl_DragDrop;
    _UserControl.DragEnter += _UserControl_DragEnter;

    string ColorName = toolTip1.GetToolTip(_PictureBox);
    string ColorCode = toolTip2.GetToolTip(_PictureBox);
    toolTip1.SetToolTip(_UserControl.pictureBox1, ColorName);
    toolTip2.SetToolTip(_UserControl.pictureBox1, ColorCode);
    toolTip2.Active = false;

    _UserControl.PictureClick += new EventHandler(ClusterControl_Click);
    _UserControl.TrackBarScroll += new EventHandler(GetTartanCode);

    foreach (Control subcontrol in _UserControl.Controls)
    {
        if (subcontrol.GetType() == typeof(GroupBox)){
            subcontrol.MouseMove += _UserControl_MouseMove;
            subcontrol.DragDrop += _UserControl_DragDrop;
            subcontrol.DragEnter += _UserControl_DragEnter;
        }
    }

    panel3.Controls.Add(_UserControl);
    panel3.Controls.SetChildIndex(_UserControl, 0);
}

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

private void _UserControl_DragDrop(object sender, DragEventArgs e)
{
    UserControl1 target = sender as UserControl1;
    if (target != null)
    {
        int targetIndex = FindUserControlIndex(target);
        if (targetIndex != -1)
        {
            string _UserControlFormat = typeof(UserControl1).FullName;
            if (e.Data.GetDataPresent(_UserControlFormat))
            {
                UserControl1 source = e.Data.GetData(_UserControlFormat) as UserControl1;

                int sourceIndex = this.FindUserControlIndex(source);

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

private int FindUserControlIndex(UserControl1 _UserControl)
{
    for (int i = 0; i < this.panel3.Controls.Count; i++)
    {
        UserControl1 target = this.panel3.Controls[i] as UserControl1;

        if (_UserControl == target)
            return i;
    }
    return -1;
}

private void _UserControl_MouseMove(object sender, MouseEventArgs e)
{
    if (e.Button == MouseButtons.Left)
    {
        if (sender.GetType() == typeof(GroupBox))
        {
            GroupBox _GroupBox = sender as GroupBox;
            UserControl1 _UserControl1 = _GroupBox.Parent as UserControl1;
            _UserControl1.BorderStyle = BorderStyle.Fixed3D;
            _UserControl1.DoDragDrop(_UserControl1, DragDropEffects.All);
        }
        else
        {
            UserControl1 _UserControl1 = sender as UserControl1;
            _UserControl1.BorderStyle = BorderStyle.Fixed3D;
            _UserControl1.DoDragDrop(_UserControl1, DragDropEffects.All);
        }
    }
}
John Schultz
  • 672
  • 1
  • 10
  • 29