Удалить динамические элементы управления внутри панели с динамическими кнопками

Мой код динамически создает метку с белым фоном внутри панели одним нажатием кнопки. Над каждой динамически созданной меткой находится красная кнопка «X», которую можно использовать для удаления каждой метки.
Все работает, за исключением того, что я могу удалить только последнюю созданную метку. Я хотел бы, чтобы код удалял каждую метку по одной.

Я знаю, что panel1.controls.clear() удалит все на панели, но я хочу удалить каждую метку по отдельности с помощью кнопки удаления, созданной на метке.

Public Class Form1
    Dim counter As Integer = 0
    Dim MyControls As List(Of Control)

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        MyControls = New List(Of Control)
        Dim lblBg As New Label 
        Dim btnDelete As New Button

        lblBg.Size = New Size(230, 200)
        lblBg.Location = New Point(counter * 240, 10)
        lblBg.BackColor = Color.White
        lblBg.ForeColor = Color.Black

        btnDelete.Name = "btn" & counter
        btnDelete.Size = New Size(25, 25)
        btnDelete.Location = New Point(counter * 240, 10)
        btnDelete.BackColor = Color.White
        btnDelete.ForeColor = Color.Red
        btnDelete.Font = New System.Drawing.Font("Arial", 10.0!, System.Drawing.FontStyle.Bold)
        btnDelete.Text = "x"
        btnDelete.FlatAppearance.BorderSize = 0
        btnDelete.FlatStyle = FlatStyle.Flat
        AddHandler btnDelete.Click, AddressOf ButtonClick

        Panel1.Controls.Add(btnDelete)
        MyControls.Add(btnDelete)
        Panel1.Controls.Add(lblBg)
        MyControls.Add(lblBg)
        counter += 1
    End Sub

    Private Sub ButtonClick(sender As Object, e As EventArgs)
        counter = 0
        For Each c As Control In MyControls
            Panel1.Controls.Remove(c)
            c.Dispose()
        Next
    End Sub
End Class

Будем признательны за любую помощь опытного программиста VB!

Brianalanvh 02.07.2019 03:07

Назначьте Label, который вы только что создали, свойству Tag только что созданного Button. В обработчике событий Click получите Button из параметра sender, получите Label из Tag из Button, а затем Remove их обоих из Panel. Не забудьте удалить обработчик события из файла Button.

jmcilhinney 02.07.2019 04:13

Кроме того, вам действительно следует использовать TableLayoutPanel или FlowLayoutPanel для автоматического позиционирования элементов управления. Кроме того, вам следует подумать о разработке собственного пользовательского элемента управления, содержащего Label и Button. Таким образом, весь блок будет автономным.

jmcilhinney 02.07.2019 04:14
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
3
62
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Проблема в том, что вы воссоздаете List(Of Control) каждый раз, когда создается новая метка, поэтому список будет содержать только последнюю добавленную вами метку. При попытке удалить одну из меток вы перебираете всю коллекцию. Если бы List(Of Control) обслуживался должным образом, вы удалили бы все элементы управления.

Кстати, не используйте это:

Panel1.Controls.Remove(c)

Просто вызовите [Control].Dispose(), вы избавитесь от объекта, и это также удалит его из коллекции контейнеров.

Другая, более тонкая проблема заключается в том, как вы позиционируете элементы управления в контейнере Panel: вам будет трудно переместить один из элементов управления на прежнее место (при необходимости), когда элемент управления будет удален. Используя этот счетчик, вы только увеличиваете позицию Location.X.

Я предлагаю добавить FlowLayoutPanel в панель, которую вы используете для размещения элементов управления. Поместите его внутрь панели, установите для его свойства Док значение DockStyle.Fill, затем добавьте в него свои элементы управления, он позаботится об их размещении за вас. Кнопка должна быть родитель с меткой, чтобы работать правильно.
Вы также можете создать UserControl вместо пары стандартных элементов управления.

Здесь свойство Tag кнопки используется для ссылки на метку, которой она принадлежит. Когда кнопка нажата, объект sender будет кнопкой, вызвавшей событие, вам просто нужно привести sender к Button (или Control), чтобы получить доступ к ее свойствам.
Свойство Tag используется для удаления связанной метки. Обработчик события также должен быть незарегистрированный.

Примечание: в этом коде FlowLayoutPanel называется flp1.

Private Sub btnAddLabel_Click(sender As Object, e As EventArgs) Handles btnAddLabel.Click

    Dim lblBg As New Label() With {
        .BackColor = Color.White,
        .ForeColor = Color.Black,
        .Size = New Size(230, 200)
    }

    Dim btnDelete As New Button() With {
        .BackColor = Color.White,
        .ForeColor = Color.Red,
        .Font = New Font("Arial", 10.0!, FontStyle.Bold),
        .Location = New Point(0, 0),
        .Parent = lblBg,
        .Size = New Size(25, 25),
        .Tag = lblBg,
        .Text = "x"
    }
    btnDelete.FlatAppearance.BorderSize = 0
    btnDelete.FlatStyle = FlatStyle.Flat
    AddHandler btnDelete.Click, AddressOf ButtonDeleteClick
    flp1.Controls.Add(lblBg)
End Sub

Private Sub ButtonDeleteClick(sender As Object, e As EventArgs)
    Dim ctrl As Control = DirectCast(sender, Control)
    DirectCast(ctrl.Tag, Control).Dispose()
    RemoveHandler ctrl.Click, AddressOf ButtonDeleteClick
    ctrl.Dispose()
End Sub

вау спасибо большое за подробное объяснение. Мне эта информация очень пригодилась!

Brianalanvh 02.07.2019 06:12

Другие вопросы по теме