Список в качестве свойств. Не добавлять кнопки на панель

#c# #winforms

#c# #winforms

Вопрос:

Я пытаюсь создать пользовательскую панель, где я могу изменять свойства, используя Свойства -> Кнопки -> [(Коллекция) …]:

Следующее, что я пробовал

 public class CustomPanel : Panel
{
    private List<Button> buttons = new List<Button>();

    public List<Button> Buttons
    {
        get { return buttons; }
        set 
        {
             buttons = value;
             this.Controls.Clear();
                
             foreach (var button in buttons)
             {
                button.Size = new Size(200, 30);
                this.Controls.Add(button);
             }
         }
    }
}
  

Но когда я добавляю новую кнопку с помощью Properties -> Buttons -> [(Collection) …]: она не добавляет ее на мою панель.

Комментарии:

1. Вы также должны каким-то образом указать местоположение!

2. Обратите внимание, что параметр свойства будет срабатывать только при назначении ему объекта списка, а не при добавлении элементов в этот список. Я не совсем уверен, что вы имеете в виду Properties -> Items -> [(Collection) ...] .

3. @TaW я могу это сделать, но в любом случае это не войдет в мой список

4. Ваш код работает не так, как ожидалось, потому List<> что это коллекция сама по себе, а Panel.Controls это совершенно другая коллекция!! Вам необходимо синхронизировать их в обоих направлениях каждый раз, когда один из них изменяется, но List<> не допускает такого поведения. Возможно, изменение List<Button> на Button[] может разрешить или помочь. Вам следует переосмыслить цели такого подхода: вам нужна коллекция Button элементов управления только потому, что вы хотите отфильтровать любой другой вид Control , или… вы хотите Button , чтобы на панель добавлялись только элементы управления?

5. @TaW обратите внимание, что проблема, вероятно, возникает в окне свойств конструктора, который вы не можете отлаживать, если не запустите второй экземпляр среды разработки (Visual Studio ?) и Не присоедините его отладчик к экземпляру, в котором запущен конструктор. Альтернативой реальному отладчику может быть ведение журнала / отображение сообщений (MessageBox . Показать, консоль. WriteLine или пользовательская альтернатива) путем добавления явных инструкций по всему коду для отладки.

Ответ №1:

Предполагая CustomPanel , что класс был добавлен в качестве пользовательского элемента управления, а его базовый класс изменен на Panel , вы можете попробовать следующий код.

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

namespace TEST
{
    public partial class CustomPanel : Panel
    {
        public CustomPanel()
        {
            InitializeComponent();
        }

        [Editor(typeof(ArrayEditor), typeof(UITypeEditor))]
        public Button[] Buttons
        {
            get { return this.Controls.OfType<Button>().ToArray(); }
            set
            {
                SuspendLayout();
                try
                {
                    this.Controls.Clear();

                    foreach (var button in value)
                    {
                        button.Size = new Size(200, 30);
                        this.Controls.Add(button);
                    }
                }
                finally { ResumeLayout(); }
            }
        }
    }
}
  

Убедитесь, что в проекте есть ссылка на System.Design.dll , для ArrayEditor распознавания.

Имейте в виду, что:

  • Каждый Button элемент управления, добавленный дизайнером через Buttons свойство, будет сериализован, как он был добавлен обычным способом проектирования.
  • Добавление других (не Button ) элементов управления по-прежнему возможно обычным способом проектирования или программно.
  • this.Controls.Clear удалит любой элемент управления, даже те, которые добавлены без использования Buttons ; вы можете удалить эту инструкцию, если хотите сохранить их, но вам понадобится способ распознать ранее существующие кнопки и заменить или сохранить их по мере необходимости.
  • Все свойства любого Button объекта можно редактировать внутри ArrayEditor формы.
  • Вам необходимо обработать позиционирование элементов Button управления (как недавно добавленных, так и существующих), чтобы избежать дублирования.

Я предлагаю использовать дочерний FlowLayoutPanel элемент для автоматического позиционирования кнопок и для предотвращения непосредственного доступа к коллекции кнопок. При таком подходе this.Controls станет flowLayoutPanel1.Controls (или похожим). В противном случае вы должны переопределить OnControlAdded и OnControlRemoved получать уведомления, когда какой-либо элемент управления добавляется или удаляется.