Найти индекс строки элемента управления, добавленного в TableLayoutPanel

Мне нужно выполнить действие, когда элемент управления добавляется в TableLayoutPanel в Windows Forms. Я обрабатываю событие ParentChanged элемента управления, чтобы узнать, добавлен ли элемент управления к родителю (здесь TableLayoutPanel), но полученный индекс равен -1.

Панель макета таблицы т;

private void button1_Click(object sender, EventArgs e)
{
    // this.Text = tableLayoutPanel1.Height.ToString();

    t = new TableLayoutPanel();
    t.Dock = DockStyle.Fill;
    //t.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
    t.AutoSize = true;
    //t.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
    t.RowStyles.Add(new RowStyle(SizeType.AutoSize));
    t.RowStyles.Add(new RowStyle(SizeType.AutoSize));
    t.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 50));
    t.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 50));
    panel1.Controls.Add(t);

    t.CellBorderStyle = TableLayoutPanelCellBorderStyle.Single;


    Label lbl = new Label();
    lbl.ParentChanged += new EventHandler(lbl_ParentChanged);
    lbl.Margin = new System.Windows.Forms.Padding(20, 150, 20, 20);
    lbl.Text = "Hello";
    t.Controls.Add(lbl, 0, 0);
}

void lbl_ParentChanged(object sender, EventArgs e)
{
    Label lbl = (Label)sender;
    int row = t.GetRow(lbl);//here I get row = -1 ??????
}

Мне нужен номер строки, к которой добавляется элемент управления. Элемент управления должен действовать независимо от того, когда он добавлен в TableLayoutPanel. Как его получить ?

    void t_ControlAdded(object sender, ControlEventArgs e)
    {
        int row = t.GetRow(e.Control);      //this also gives row = -1      
    }

person Brij    schedule 09.10.2012    source источник
comment
Вы нашли решение этой проблемы?.. У меня точно такая же проблема.. Можете ли вы рассказать о решении, которое сработало для вас..   -  person too_cool    schedule 01.03.2016


Ответы (3)


Вам нужно увеличить RowCount/ColumnCount, если вы добавите новый RowStyles/ColumnStyles к вашему TableLayoutPanel. После этого вы можете легко использовать метод GetPositionFromControl(Control value).

Я думаю, что ControlAdded Событие - лучший подход в этом случае. Попробуйте.

Сделай это так:

public partial class Form1 : Form
{
    private TableLayoutPanel panel;

    public Form1()
    {
        InitializeComponent();
        InitializeTableLayoutPanel();
    }

    private void Form1_Load(object sender, EventArgs e)
    {
        AddControl(0, 0);
        AddControl(0, 1);
        AddControl(1, 0);
        AddControl(1, 1);
        AddControl(2, 0);
        AddControl(2, 1);
        AddControl(3, 0);
        AddControl(3, 1);
    }

    private void InitializeTableLayoutPanel()
    {
        panel = new TableLayoutPanel();
        panel.Dock = DockStyle.Fill;
        panel.AutoSize = true;
        panel.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 50));
        panel.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 50));
        panel.ColumnCount = 2;
        panel.RowStyles.Add(new RowStyle(SizeType.AutoSize));
        panel.RowStyles.Add(new RowStyle(SizeType.AutoSize));
        panel.RowCount = 2;

        panel.CellBorderStyle = TableLayoutPanelCellBorderStyle.Single;
        panel.ControlAdded += new ControlEventHandler(OnControlAdded);

        this.Controls.Add(panel);
    }

    private void OnControlAdded(object sender, ControlEventArgs e)
    {
        if (e.Control != null)
        {
            int column = panel.GetPositionFromControl(e.Control).Column;
            int row = panel.GetPositionFromControl(e.Control).Row;

            MessageBox.Show(string.Format("Column: {0}, Row: {1}", column, row));
        }
    }

    /// <summary>
    /// Add Control to Panel
    /// </summary>
    /// <param name="column">column position</param>
    /// <param name="row">row position</param>
    private void AddControl(int column, int row)
    {
        Label label = new Label();
        label.Font = new Font(new FontFamily("Droid Sans"), 20, FontStyle.Bold);
        label.Name = "label";
        label.Text = "Whoop!";

        if (column < panel.ColumnCount && row < panel.RowCount)
            panel.Controls.Add(label, column, row);
        else
            throw new ArgumentOutOfRangeException();
    }
}
person varg    schedule 09.10.2012
comment
После установки RowCount/ColumnCount я могу получить индекс строки/столбца в событии ControlAdded. Тем не менее, это не работает для элемента управления, который добавляется в его событие ParentChanged. - person Brij; 10.10.2012

Попробуйте сделать свой материал button1_Click после того, как вы оставили сообщение (сообщение очереди сообщений Windows):

SynchronizationContext.Current.Post(new SendOrPostCallback(delegate(object state)
{
  //Your code here...
}), true);
person Peter Larsen 'CPH'    schedule 09.10.2012
comment
Элементы управления добавляются в TableLayoutPanel из различных источников. button1_click — это всего лишь пример кода, который я написал. - person Brij; 09.10.2012
comment
Ну, идея в том, что вы можете получить непредсказуемый результат, если событие вызовет даже - как видно во многих ситуациях, верно!! - person Peter Larsen 'CPH'; 10.10.2012

На странице msdn:

Положение строки элемента управления или -1, если положение элемента управления определяется LayoutEngine.

Используйте следующее:

public void ControlAdded(object sender, EventArgs e)
{
    var row = layout.GetPositionFromControl(lbl);//0,0
}
person Carra    schedule 09.10.2012
comment
layout.GetPositionFromControl(lbl) всегда дает (0,0), даже если элемент управления добавляется в другой индекс строки/столбца. - person Brij; 09.10.2012
comment
Я сделал еще несколько тестов. Это работает, если вы используете его после добавления (layout.controls.add(x,0,0) › layout.GetPositionFromControl(x), а не в событии controladded. - person Carra; 09.10.2012
comment
Итак, вы вызываете layout.controls.add(x,0,0), а затем вызываете layout.GetPositionFromControl(x). Но в моем случае X — это элемент управления, и я хочу, чтобы он реагировал в тот момент, когда он добавляется к родителю (здесь TableLayoutPanel). Поэтому я использовал ParentChanged of X. - person Brij; 09.10.2012