Daniel Weston
Daniel Weston

Reputation: 35

Swapping control position in TableLayoutPanel

EDIT:

Okay so for clarity I will improve my information a bit more:

I have a TableLayoutView (I will call this tlv) that has 5 fixed columns, and x + 2 rows. The first row of tlv contains labels in each cell for header purposes. I dynamically add more rows onto tlv and so that it why it has a variable amount of rows (plus the initial header row which is never removed).

As another tiny small complication, I also keep an empty row entry at the bottom of tlv which I must keep because I use it for other functionality.

To visualise what I have just said, this is an example of tlv consisting with 4 entries (numbered), the header row (H's) and the placeholder row (P's).

HHHHH
11111
22222
33333
44444
PPPPP

I want to go from that, to say, if I wanted to swap entry 2 and 3 the output would be:

HHHHH
11111
33333
22222
44444
PPPPP

The code I have so far is as follows:

for (int j = 0; j < 5; j++)
{
    TableLayoutPanelCellPosition tablePosition1 = new 
    TableLayoutPanelCellPosition(j, rowIndex + 1);
    Control moveControl1 = queuedFiles.GetControlFromPosition(j, rowIndex);
    queuedFiles.SetCellPosition(moveControl1, tablePosition1);

    TableLayoutPanelCellPosition tablePosition2 = new 
    TableLayoutPanelCellPosition(j, rowIndex);
    Control moveControl2 = queuedFiles.GetControlFromPosition(j, rowIndex + 1);
    queuedFiles.SetCellPosition(moveControl2, tablePosition2);

    if (j.Equals(0))
    {
        moveControl1.Text = (rowIndex + 1).ToString();
        moveControl2.Text = (rowIndex).ToString();
    }
}

However this code doesn't work and for the example above it produces:

HHHHH
11111
33222
22333
44444
PPPPP

What I believe is happening is tlv is automatically organising it's contents itself during the process of moving them around (maybe to fill vacant spaces?).

rowIndex above is the index of the target row which must be swapped with the row below it. I don't need to worry about checking if there is only 1 row or if it is the last row because I have done that already. Ignore changing the text too, I just need a pointer as to how I can achieve the intended result!

Thank you for absolutely any help you can give :)

Upvotes: 2

Views: 1831

Answers (1)

aybe
aybe

Reputation: 16652

The following code does the job:

Code

using System;
using System.Linq;
using System.Windows.Forms;

namespace WindowsFormsApp1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            // some content
            var panel = new TableLayoutPanel
            {
                Dock = DockStyle.Fill,
                ColumnCount = 5,
                RowCount = 2
            };

            for (var y = 0; y < 2; y++)
            for (var x = 0; x < 5; x++)
            {
                var control = new Button {Text = $@"X = {x}, Y = {y}"};
                panel.Controls.Add(control, x, y);
            }

            // swap button
            var button = new Button
            {
                Dock = DockStyle.Fill,
                Text = @"Clicky !"
            };

            button.Click += (o, args) =>
            {
                var dictionary = panel.Controls
                    .Cast<Control>()
                    .ToDictionary(k => k, v => panel.GetCellPosition(v));

                foreach (var pair in dictionary)
                {
                    var position = pair.Value;
                    position.Row ^= 1; // simple row swap
                    panel.SetCellPosition(pair.Key, position);
                }
            };

            // add to form
            var container = new SplitContainer
            {
                Dock = DockStyle.Fill,
                Orientation = Orientation.Horizontal,
                SplitterWidth = 5,
                BorderStyle = BorderStyle.Fixed3D
            };

            container.Panel1.Controls.Add(panel);
            container.Panel2.Controls.Add(button);

            Controls.Add(container);
        }
    }
}

Before

enter image description here

After

enter image description here

Note

Next time you ask a question, post a Minimal, Complete, and Verifiable example to maximize your chances of getting an answer !

As on why your code didn't work, see previous sentence, e.g what was rowIndex etc ?

Edit

using System;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;

namespace WindowsFormsApp1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            const int cols = 5;
            const int rows = 6;

            // setup layout
            var tlp = new TableLayoutPanel
            {
                ColumnCount = cols,
                RowCount = rows,
                Dock = DockStyle.Fill,
                GrowStyle = TableLayoutPanelGrowStyle.FixedSize
            };

            for (var i = 0; i < cols; i++)
                tlp.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100.0f / cols));

            // add header
            var label = new Label
            {
                Text = @"My Header",
                BackColor = Color.Red,
                Dock = DockStyle.Fill,
                TextAlign = ContentAlignment.MiddleCenter
            };
            tlp.Controls.Add(label);
            tlp.SetColumn(label, 0);
            tlp.SetRow(label, 0);
            tlp.SetColumnSpan(label, cols);

            // add some cells
            var yMin = 1;
            var yMax = 5;
            var xMin = 0;
            var xMax = cols;
            for (var y = yMin; y < yMax; y++)
            for (var x = xMin; x < xMax; x++)
            {
                var color = Color.FromArgb(
                    255 / (xMax - xMin) * (x - xMin),
                    128,
                    255 / (yMax - yMin) * (y - yMin)
                );
                var label1 = new Label
                {
                    Text = $@"X = {x}, Y = {y}",
                    BackColor = color,
                    ForeColor = Color.White,
                    Dock = DockStyle.Fill,
                    TextAlign = ContentAlignment.MiddleCenter,
                    Margin = DefaultMargin
                };
                tlp.Controls.Add(label1, x, y);
            }

            // add swapper
            var button = new Button
            {
                Text = @"Clicky !",
                Dock = DockStyle.Fill
            };
            button.Click += (o, args) =>
            {
                var srcRow = 2;
                var tgtRow = 3;
                var controls = tlp.Controls.Cast<Control>().ToArray();
                var array1 = controls.Where(s => tlp.GetRow(s) == srcRow).ToArray();
                var array2 = controls.Where(s => tlp.GetRow(s) == tgtRow).ToArray();

                foreach (var control in array1)
                    tlp.SetCellPosition(control, new TableLayoutPanelCellPosition(tlp.GetColumn(control), tgtRow));

                foreach (var control in array2)
                    tlp.SetCellPosition(control, new TableLayoutPanelCellPosition(tlp.GetColumn(control), srcRow));
            };

            // pack things up
            var sc = new SplitContainer
            {
                Orientation = Orientation.Horizontal,
                BorderStyle = BorderStyle.Fixed3D,
                Dock = DockStyle.Fill
            };
            sc.Panel1.Controls.Add(tlp);
            sc.Panel2.Controls.Add(button);
            Controls.Add(sc);
        }
    }
}

enter image description here

enter image description here

Upvotes: 1

Related Questions