Изменение порядка Z при отображении закрепленных элементов управления

Я использую С# Winforms с .NET Framework версии 4.0.

У меня есть панель с четырьмя метками, прикрепленными к верхней части панели. Две средние метки скрыты.

---Вверху---
Ярлык один (видимый)
Ярлык второй - (НЕ виден)
Ярлык третий (НЕ виден)
Ярлык четвертый - (видимый)
---Внизу---

При нажатии кнопки с кодом ниже

private void btnShowLabels_Click(object sender, EventArgs e)
{
    this.lblTwo.Visible = true;
    this.lblThree.Visible = true;
}

метки два и три появляются, но их z-порядок перепутан, как показано ниже.

---Верх---
Ярлык Один (видимый)
Ярлык Три (видимый)
Ярлык Два - (видимый) < br/>Ярлык четыре - (видимый)
---Внизу---

Почему меняется z-порядок и как я могу остановить это.

Я понимаю, что могу переупорядочить все метки, используя BringToFront() внутри события click, но это кажется излишним, особенно для более сложных механизмов стыковки.


person user1085489    schedule 26.02.2014    source источник
comment
Пробовали ли вы изменить порядок ваших .visible вызовов?   -  person user2320861    schedule 26.02.2014
comment
Я наткнулся на эту публикацию при изучении вашего вопроса. Вы пытались установить индекс каждой метки, используя метод SetChildIndex в родительской коллекции Controls?   -  person Mark    schedule 26.02.2014


Ответы (3)


Порядок стыковки немного отличается от z-порядка, и с помощью SetChildIndex вам все равно придется назначать свойство .Visible каждой метки в определенном порядке. Я играл с этим, пытаясь заставить lbl1 и lbl4 появляться в другом порядке, но они всегда остаются на своих местах. Я думаю, что вам лучше всего просто назвать «средние» метки в «обратном» порядке, чем вы обычно думаете.

РЕДАКТИРОВАТЬ: вот способ, которым вы всегда можете сохранить один и тот же порядок док-станции, не беспокоясь о том, чтобы все время устанавливать видимое свойство каждой метки в порядке. Просто создайте этот обработчик событий, который вы можете прикрепить к событию VisibleChanged каждой закрепленной метки:

void GenericDockedLabel_VisibleChanged(object sender, EventArgs e)
{
    this.Controls.SetChildIndex(lbl1, 3);
    this.Controls.SetChildIndex(lbl2, 2);
    this.Controls.SetChildIndex(lbl3, 1);
    this.Controls.SetChildIndex(lbl4, 0);
}

Поддерживает @Mark для нахождения SetChildIndex

person user2320861    schedule 26.02.2014

Установка Control.Visible = True иногда изменяет Z-порядок. Кажется, это зависит от создания дескриптора.

Мне отлично помогло это (очевидно бессмысленное) утверждение:

foreach (Control ctrl in FlpDetails.Controls)
{
    IntPtr DummyHandle = ctrl.Handle;
}

Это заставляет все элементы управления создавать дескрипторы. После этого control.visible = true больше не меняет Z-порядок.

Я получил это решение с внешнего веб-сайта, который теперь перенаправляет на рыболовный веб-сайт.

person Ted    schedule 13.05.2015
comment
Это кажется немного хакерским, но определенно сработало для меня. - person Jake R; 29.07.2015
comment
Теперь ваша ссылка ведет на какой-то рыболовный сайт. Если бы вы могли найти альтернативный источник, было бы здорово - person Neuron; 05.09.2018

Для моего приложения пользователь мог выбрать количество строительных панелей (до 5), которые он хотел, в поле со списком, и программа затем отображала пронумерованную панель для каждой, где они могли ввести размеры (высота, ширина, толщина) для каждой панель. Была создана панель с меткой заголовка с номером панели, а также текстовыми полями и метками для высоты, ширины и толщины. Все панели были закреплены слева от содержащей их панели для управления компоновкой. К сожалению, скрытие и отображение панелей на основе выбранного значения в поле со списком приводило к тому, что панели отображались в полуслучайном порядке.

private void cboNumberOfPanels_SelectedIndexChanged(object sender, EventArgs e)
{
    int numberOfPanels;
    int.TryParse(cboNumberOfPanels.SelectedItem.ToString(), out numberOfPanels);

    pnlPanelDimensions1.Visible = numberOfPanels >= 1;
    pnlPanelDimensions2.Visible = numberOfPanels >= 2;
    pnlPanelDimensions3.Visible = numberOfPanels >= 3;
    pnlPanelDimensions4.Visible = numberOfPanels >= 4;
    pnlPanelDimensions5.Visible = numberOfPanels >= 5;
}

Я попытался использовать предложение .SetChildIndex() выше, но все же столкнулся с проблемами при втором выборе. Например, если бы я выбрал 1, pnlPanelDimensions1 отобразился бы в правильной позиции. Если затем выбрать 3, я бы сначала отобразил pnlPanelDimensions2, затем pnlPanelDimensions3 и, наконец, pnlPanelDimensions1. При всех последующих изменениях после второго все отображалось корректно.

Наконец-то я нашел вариант, который работал правильно каждый раз в моем решении:

    int numberOfPanels;
    int.TryParse(cboNumberOfPanels.SelectedItem.ToString(), out numberOfPanels);

    pnlPanelDimensions1.Visible = numberOfPanels >= 1;
    pnlPanelDimensions1.BringToFront();
    pnlPanelDimensions2.Visible = numberOfPanels >= 2;
    pnlPanelDimensions2.BringToFront();
    pnlPanelDimensions3.Visible = numberOfPanels >= 3;
    pnlPanelDimensions3.BringToFront();
    pnlPanelDimensions4.Visible = numberOfPanels >= 4;
    pnlPanelDimensions4.BringToFront();
    pnlPanelDimensions5.Visible = numberOfPanels >= 5;
    pnlPanelDimensions5.BringToFront();
person CEhret    schedule 16.10.2019