Как рекурсивно изменить цвет меток в нескольких формах - PullRequest
1 голос
/ 11 апреля 2020

У меня есть небольшое приложение с формой настроек. Там определенная кнопка при нажатии изменит цвет всех надписей в Panel4 в каждой из форм (Basic, Easy, Medium, Hard, Advanced). Я получил это, чтобы работать по одному с For-Each l oop, как показано ниже:

For Each lbl As Label In Basic.Panel4.Controls.OfType(Of Label)
            lbl.ForeColor = Color.White
Next

For Each lbl As Label In Easy.Panel4.Controls.OfType(Of Label)
      etc...

Я хочу знать, есть ли более эффективный способ выполнить это, чем повторять по сути одно и то же 5 раз. Я пробовал следующее:

Dim lst As New List(Of Form) From {Basic, Easy, Medium, Hard, Advanced}
For Each frm As Form In lst
    For Each lbl As Label In frm.Panel4.Controls.OfType(Of Label)
        lbl.ForeColor = Color.White
    Next
Next

Но получаю ошибку, что 'Panel4' is not a member of 'Form'

1 Ответ

2 голосов
/ 11 апреля 2020

Проблема в том, что тип c вашего * generic List равен Form, а в классе Form нет члена с именем Panel4. У вас есть несколько определенных c типов, каждый из которых имеет определенный c член с таким именем, но общее имя в любом случае не делает их одним и тем же членом. Есть несколько способов справиться с этим.

Во-первых, быстрый и грязный способ. Это небольшая настройка того, что вы уже делаете:

Dim forms As Form() = {Basic, Easy, Medium, Hard, Advanced}

For Each frm In forms
    For Each lbl As Label In frm.Controls("Panel4").Controls.OfType(Of Label)
        lbl.ForeColor = Color.White
    Next
Next

Обратите внимание, что первое изменение заключается в использовании массива для хранения форм, а не коллекции. Весь смысл коллекционирования в том, что он растет и сжимается по мере необходимости. Если вы никогда не меняете список после его создания, какой в ​​этом смысл?

Хотя важное изменение заключается во внутреннем l oop. Класс Form имеет свойство Controls, и вы можете индексировать его по имени, чтобы получить указанный c элемент управления. Все ваши Panels имеют одинаковые имена, так что вы можете использовать эту технику, чтобы получить доступ к каждому. Это возвращает ссылку Control, но это все, что вам нужно, чтобы получить коллекцию Controls для доступа к каждому Label.

. Правильный способ справиться с этим - начать с создания базовой формы с один или несколько указанных c членов, а затем получая из этого все остальные пять ваших форм. Такая форма может содержать такой код:

Public Class ColouredLabelForm

    Protected Property LabelPanel As Panel

    Public Sub SetLabelForeColors(colour As Color)
        For Each lbl In LabelPanel.Controls.OfType(Of Label)()
            lbl.ForeColor = colour
        Next
    End Sub

End Class

Каждая из ваших производных форм может выглядеть следующим образом:

Public Class Form1

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        LabelPanel = Panel4
    End Sub

End Class

Код для изменения всех Labels становится таким :

Dim forms As ColouredLabelForm() = {Basic, Easy, Medium, Hard, Advanced}

For Each frm In forms
    frm.SetLabelForeColors(Color.White)
Next

Правильный способ внесения изменений в элементы управления или данные в формах - ВСЕГДА заставить форму делать это самостоятельно, а не делать это с формой извне. Вы говорите форме, что делать снаружи, а затем форма делает это.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...