Добавление текстового поля в табличную панель выводит текстовое поле в "случайные" места

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

В приведенном примере кода я пытаюсь добавить текстовое поле в индекс строки 2, но когда я перетаскиваю содержимое из списка в панель таблицы, он просто добавляет текстовое поле в "случайных" местах, как показано на скриншоте ниже.

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

Я ожидаю, что существующие текстовые поля сместятся вниз и освободят место для добавляемого текстового поля, насколько я понимаю из этого: https://social.msdn.microsoft.com/Forums/windows/en-US/e4312cd8-6031-4a5c-92bf-e8adb1941fe5/insert-row-at-particular-position-in-table-layout-panel?forum=winforms.

Я делаю что-то неправильно?

Код дизайнера:

partial class Form1
{
    /// <summary>
    /// Required designer variable.
    /// </summary>
    private System.ComponentModel.IContainer components = null;

    /// <summary>
    /// Clean up any resources being used.
    /// </summary>
    /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
    protected override void Dispose(bool disposing)
    {
        if (disposing && (components != null))
        {
            components.Dispose();
        }
        base.Dispose(disposing);
    }

    #region Windows Form Designer generated code

    /// <summary>
    /// Required method for Designer support - do not modify
    /// the contents of this method with the code editor.
    /// </summary>
    private void InitializeComponent()
    {
        this.listBox1 = new System.Windows.Forms.ListBox();
        this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();
        this.SuspendLayout();
        // 
        // listBox1
        // 
        this.listBox1.FormattingEnabled = true;
        this.listBox1.Location = new System.Drawing.Point(367, 12);
        this.listBox1.Name = "listBox1";
        this.listBox1.Size = new System.Drawing.Size(190, 407);
        this.listBox1.TabIndex = 0;
        this.listBox1.MouseDown += new System.Windows.Forms.MouseEventHandler(this.listBox1_MouseDown);
        // 
        // tableLayoutPanel1
        // 
        this.tableLayoutPanel1.ColumnCount = 1;
        this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F));
        this.tableLayoutPanel1.Location = new System.Drawing.Point(13, 12);
        this.tableLayoutPanel1.Name = "tableLayoutPanel1";
        this.tableLayoutPanel1.RowCount = 1;
        this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50F));
        this.tableLayoutPanel1.Size = new System.Drawing.Size(332, 407);
        this.tableLayoutPanel1.TabIndex = 1;
        this.tableLayoutPanel1.DragDrop += new System.Windows.Forms.DragEventHandler(this.tableLayoutPanel1_DragDrop);
        this.tableLayoutPanel1.DragEnter += new System.Windows.Forms.DragEventHandler(this.tableLayoutPanel1_DragEnter);
        // 
        // Form1
        // 
        this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
        this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
        this.ClientSize = new System.Drawing.Size(569, 431);
        this.Controls.Add(this.tableLayoutPanel1);
        this.Controls.Add(this.listBox1);
        this.Name = "Form1";
        this.Text = "Form1";
        this.ResumeLayout(false);

    }

    #endregion

    private System.Windows.Forms.ListBox listBox1;
    private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1;
}

Код формы:

public partial class Form1 : Form
{
    private int tempInt = 0;

    public Form1()
    {
        InitializeComponent();
        listBox1.Items.AddRange(new object[] { "test" });
        tableLayoutPanel1.AllowDrop = true;
        tableLayoutPanel1.GrowStyle = TableLayoutPanelGrowStyle.AddRows;
        tableLayoutPanel1.AutoScroll = true;
        tableLayoutPanel1.RowCount = 3;
    }

    private void listBox1_MouseDown(object sender, MouseEventArgs e)
    {
        tempInt++;
        DoDragDrop("test" + tempInt, DragDropEffects.Copy);
    }

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

    private void tableLayoutPanel1_DragDrop(object sender, DragEventArgs e)
    {
        string text = e.Data.GetData(typeof(String)) as string;
        TextBox tb = new TextBox();
        tb.Dock = DockStyle.Fill;
        tb.Text = text;
        // I want to add the textbox to the second row
        tableLayoutPanel1.Controls.Add(tb, 0, 2);
        tableLayoutPanel1.SetRow(tb, 2);
    }
}

РЕДАКТИРОВАТЬ:

Добавлен код, основанный на предложенном ДонБойноттом

    private void tableLayoutPanel1_DragDrop(object sender, DragEventArgs e)
    {
        string text = e.Data.GetData(typeof(String)) as string;
        TextBox tb = new TextBox();
        tb.Dock = DockStyle.Fill;
        tb.Text = text;
        tableLayoutPanel1.RowStyles.Add(new RowStyle(SizeType.AutoSize));
        for (int i = 0; i < tableLayoutPanel1.Controls.Count; i++)
        {
            int pos = tableLayoutPanel1.GetRow(tableLayoutPanel1.Controls[i]);
            if (pos > 1)
            {
                tableLayoutPanel1.SetRow(tableLayoutPanel1.Controls[i], pos + 1);
            }
        }
        tableLayoutPanel1.Controls.Add(tb, 0, 2);
    }

1 ответ

Решение

Попробуйте этот измененный класс формы, я внес несколько изменений:

    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            listBox1.Items.AddRange(new Object[] { "TextBox" });
            tableLayoutPanel1.AllowDrop = true;
            tableLayoutPanel1.GrowStyle = TableLayoutPanelGrowStyle.AddRows;
            tableLayoutPanel1.AutoScroll = true;
            tableLayoutPanel1.RowStyles.Clear();
            tableLayoutPanel1.ColumnStyles.Clear();
            tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100f));
        }

        private void listBox1_MouseDown(Object sender, MouseEventArgs e)
        {
            var count = tableLayoutPanel1.Controls.Count;
            DoDragDrop($"test{count + 1}", DragDropEffects.Copy);
        }

        private void tableLayoutPanel1_DragEnter(Object sender, DragEventArgs e)
        {
            e.Effect = DragDropEffects.Copy;
        }

        private void tableLayoutPanel1_DragDrop(Object sender, DragEventArgs e)
        {
            var tb = new TextBox();
            tb.Dock = DockStyle.Fill;
            tb.Text = (e.Data.GetData(typeof(String)) as String);

            var newRow = tableLayoutPanel1.RowStyles.Add(new RowStyle(SizeType.AutoSize));
            var ctrl = tableLayoutPanel1.GetChildAtPoint(tableLayoutPanel1.PointToClient(new Point(e.X, e.Y)));
            if (ctrl != null)
            {
                var pos = tableLayoutPanel1.GetRow(ctrl);
                for (Int32 i = tableLayoutPanel1.RowStyles.Count - 2; i >= pos; i--)
                {
                    var c = tableLayoutPanel1.GetControlFromPosition(0, i);
                    if (c != null)
                        tableLayoutPanel1.SetRow(c, i + 1);
                }
                tableLayoutPanel1.Controls.Add(tb, 0, pos);
            }
            else
                tableLayoutPanel1.Controls.Add(tb, 0, newRow);
        }
    }

Основные шаги:

  1. Я выпал на существующий контроль? Если так, определите, где.
  2. Если это так, работайте снизу вверх, перемещая каждый элемент управления вниз по слоту. Вы должны избегать дублирования, два элемента управления не могут занимать одну и ту же ячейку.
  3. Если это так, вставьте новый элемент управления в недавно освобожденный слот в точке сброса.
  4. Если нет, просто добавьте элемент управления в конце.
Другие вопросы по тегам