Переместить элемент из одной ячейки в другую

У меня есть tableLayoutPanel с 16 ячейками. 15 ячеек имеют элементы управления. Я хочу иметь возможность перемещать элементы управления из одной ячейки в другую во время выполнения.

я использовал

    private void button15_Click(object sender, EventArgs e)
    {
        tableLayoutPanel1.Controls.Remove(button15);

        tableLayoutPanel1.Controls.Add(button15, 3, 3);
    }

Это работает хорошо, но я хочу знать, есть ли лучший способ сделать это???


person Community    schedule 07.09.2013    source источник
comment
у вас есть SetRow(), SetColumn() и SetCellPosition(), последний из которых объединяет последние 2 - 3 метода принимают в качестве первого аргумента рассматриваемый элемент управления, а затем аргумент setrow 2º представляет собой целое число, чтобы поместить его в желаемую строку (setcolumn то же самое, но для нужного столбца), аргумент SetCellPosition 2º будет принимать тип TableLayoutPanelCellPosition, который устанавливает как строку, так и столбец. Вы получаете необходимый элемент управления, как этот Control c = tableLayoutPanel1.GetControlFromPosition(0, 0);, будет получать элемент управления в столбце 0 - строка 0. Надеюсь, это поможет.   -  person terrybozzio    schedule 08.09.2013
comment
@terrybozzio Спасибо, я проверю   -  person    schedule 08.09.2013


Ответы (2)


В Winforms вы можете перемещать элемент управления только внутри его родителя (конечно, есть некоторые исключения для некоторых элементов управления, которые на самом деле не имеют никакого родителя). Итак, идея здесь в том, что если вы хотите переместить элемент управления вашего TableLayoutPanel, вы должны установить его родительский элемент в свой Form другого container, когда мышь удерживается нажатой, при перемещении позиция элемента управления находится в новом родительском элементе, после мыши выпущен, мы должны установить родительский элемент управления на TableLayoutPanel назад, конечно, мы должны найти положение раскрывающейся ячейки и использовать метод SetCellPosition для размещения элемента управления на TableLayoutPanel, вот демонстрационный код для вас (работает отлично), я использую 2 Button в этой демонстрации, вы можете заменить их любым элементом управления, который вы хотите:

public partial class Form1 : Form {
    public Form1() {
        InitializeComponent();
        //This will prevent flicker
        typeof(TableLayoutPanel).GetProperty("DoubleBuffered", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance).SetValue(tableLayoutPanel1, true, null);
    }
    Point downPoint;
    bool moved;
    //This is used to store the CellBounds together with the Cell position
    //so that we can find the Cell position later (after releasing mouse).
    Dictionary<TableLayoutPanelCellPosition, Rectangle> dict = new Dictionary<TableLayoutPanelCellPosition, Rectangle>();
    //MouseDown event handler for all your controls (on the tableLayoutPanel1)
    private void Buttons_MouseDown(object sender, MouseEventArgs e) {
        Control button = sender as Control;
        button.Parent = this;            
        button.BringToFront();            
        downPoint = e.Location;            
    }
    //MouseMove event handler for all your controls (on the tableLayoutPanel1)
    private void Buttons_MouseMove(object sender, MouseEventArgs e) {
        Control button = sender as Control;
        if (e.Button == MouseButtons.Left) {
            button.Left += e.X - downPoint.X;
            button.Top += e.Y - downPoint.Y;
            moved = true;
            tableLayoutPanel1.Invalidate();
        }
    }
    //MouseUp event handler for all your controls (on the tableLayoutPanel1)
    private void Buttons_MouseUp(object sender, MouseEventArgs e) {
        Control button = sender as Control;
        if (moved) {
            SetControl(button, e.Location);
            button.Parent = tableLayoutPanel1;
            moved = false;
        }
    }
    //This is used to set the control on the tableLayoutPanel after releasing mouse
    private void SetControl(Control c, Point position) {
        Point localPoint = tableLayoutPanel1.PointToClient(c.PointToScreen(position));
        var keyValue = dict.FirstOrDefault(e => e.Value.Contains(localPoint));
        if (!keyValue.Equals(default(KeyValuePair<TableLayoutPanelCellPosition, Rectangle>))) {
            tableLayoutPanel1.SetCellPosition(c, keyValue.Key);
        }
    }
    //CellPaint event handler for your tableLayoutPanel1
    private void tableLayoutPanel1_CellPaint(object sender, TableLayoutCellPaintEventArgs e) {
        dict[new TableLayoutPanelCellPosition(e.Column, e.Row)] = e.CellBounds;
        if (moved) {
            if (e.CellBounds.Contains(tableLayoutPanel1.PointToClient(MousePosition))) {
                e.Graphics.FillRectangle(Brushes.Yellow, e.CellBounds);
            }
        }
    }
}

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

person King King    schedule 08.09.2013
comment
Используя этот код, я могу переместить кнопку в другую ячейку в TableLayoutPanel, но при повторном нажатии на кнопку они автоматически переключаются в другое место. Не могли бы вы помочь мне решить эту проблему? - person hung34k; 29.07.2017

Снимите блокировку и установите док на none и двигайтесь!

person Hari    schedule 21.08.2020
comment
Я думаю, вы пропустили требование во время выполнения. - person Klaus Gütter; 21.08.2020