Перетащите CustomControl, работающий только в фоновом режиме.

У меня есть настраиваемый элемент управления, содержащий кнопку с меткой внизу. Я хочу сделать так, чтобы эти элементы управления можно было перетаскивать поверх другого, чтобы расположить их так, как я хочу, на панели потока. Теперь работает, только если я перетащу элемент управления из его фона (отмечен желтым на рисунке ниже) в область другого элемента управления, отмеченную желтым цветом, но не если я перетащу из области кнопки или метки.

введите здесь описание изображения

Как я могу сделать так, чтобы я мог перемещать настраиваемый элемент управления независимо от того, откуда я беру и бросаю его на другой элемент управления. По сути, это должен быть только один элемент управления, а не контейнер для кнопки и метки.

Это мой код до сих пор:

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

    private void flowLayoutPanel1_DragDrop(object sender, DragEventArgs e)
    {         
        CustomControl target = sender as CustomControl;
        if (target != null)
        {
            int targetIndex = FindCSTIndex(target);
            if (targetIndex != -1)
            {
                string pictureBoxFormat = typeof(CustomControl).FullName;
                if (e.Data.GetDataPresent(pictureBoxFormat))
                {
                    CustomControl source = e.Data.GetData(pictureBoxFormat) as CustomControl;

                    int sourceIndex = this.FindCSTIndex(source);

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

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

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

    private void OnCstMouseMove(object sender, MouseEventArgs e)
    {
        if (e.Button == MouseButtons.Left)
        {
            CustomControl cst = sender as CustomControl;
            cst.DoDragDrop(cst, DragDropEffects.Move);
        }
    }

И пользовательский класс управления:

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

    public CustomControl(Button button, Label label)
    {
        _button = button;
        _label = label;
        button.Width = 50;
        button.Height = 50;
        label.Width = 65;
        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);
    }
}

person alex Alex    schedule 08.05.2014    source источник
comment
Я думал ответить на ваш двухдневный вопрос, но по каким-то причинам не стал. Вам нужно обрабатывать событие перетаскивания во всех ваших дочерних элементах управления. Можно сделать это автоматически: переопределить (ну, или подписаться) ControlAdded/СontrolRemoved событий и добавить/удалить туда события перетаскивания.   -  person Sinatr    schedule 08.05.2014
comment
Не могли бы вы привести пример? Я не уверен, как это сделать.. Спасибо!   -  person alex Alex    schedule 08.05.2014


Ответы (2)


Используйте MouseDown вместо MouseMove для запуска перетаскивания (MSDN) . Вы можете инициировать перетаскивание в самом управляющем коде (при условии, что все CustomControl будут доступны для перетаскивания), в противном случае вы можете создать общедоступный метод для подписи дочерних элементов (разоблачение дочерних элементов - плохая идея, если вы уже не использовать их снаружи).

public class CustomControl : Control
{
    ...

    public CustomControl(Button button, Label label)
    {
        ...

        _button.MouseDown += OnMouseDown;
        _label.MouseDown += OnMouseDown;
    }

    override void OnMouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
    {
        if (e.Button == MouseButtons.Left)
            (sender as Control).DoDragDrop(this, DragDropEffects.Move);
    }
}

Непроверенный, но должен дать вам представление.

person Sinatr    schedule 08.05.2014

Удалось решить:

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);
        }
    }
person alex Alex    schedule 14.05.2014