Архитектура событий Winforms - PullRequest
3 голосов
/ 12 июля 2020

Пытаюсь создать простое приложение на winforms, но замечаю пробел в моем понимании событий внутри модели winforms. Я знаю, что я довольно близок к решению, но есть несколько вещей, которые я не знаю, как сделать "путь winforms"

Вот макет пользовательского интерфейса того, что я пытаюсь выполнить sh. Form1 создается с помощью шаблона VS2019, но как LeftSide, так и RightSide - это два отдельных класса, которые я создал. текстовое поле и кнопка

имеют «дочерние» элементы управления, которые не отображаются (ie, сам класс отвечает за макет пользовательского интерфейса и проверку данных) требуют взаимодействия друг с другом и Form1 ни от чего не наследуются; они используются в Form1 через пространство имен создаются в Form1

Вот (неполная) Form1, idk, что добавить сюда

namespace myapp
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
    }
}

Здесь - это классы LeftSide и RightSide (обратите внимание, что они одинаковы, за исключением замены слова «left» на «right»)

namespace myapp.LeftSide
{
     class LeftSide
     {
            private Panel LeftSide_Panel = new Panel();
            private Textbox LeftSide_TextBox = new Textbox();
            
            private Button LeftSide_Button = new Button();

            private string LeftSide_Data; //store TextBox.text here

            public ReturnPanel()
            {
             //return a Panel that Form1 can use
             LeftSide_Panel.Controls.Add(LeftSide_Button);
             LeftSide_Panel.Controls.Add(LeftSide_TextBox);
             return this.LeftSide_Panel;
            }
      }
}

Я понимаю, что могу создать собственный обработчик событий для LeftSide_Button, создав внутри LeftSide, например:

private void LeftSide_Button_Click(object sender, EventArgs e)
{
 //read the textbox, assume it is valid and store the string in our LeftSide_Data
 this.LeftSide_Data = this.LeftSide_TextBox.Text;
}

Вышеупомянутое работает, если я хочу сохранить данные локальными для класса, но я не понимаю, как открыть LeftSide_Button_Click, в первую очередь, Form1, а иногда и RightSide.

Мои проблемы:

  • , если LeftSide владеет данными , которые находятся внутри его текстового поля (и хранятся в LeftSide_Data), а LeftSide_Button_Click - мое настраиваемое событие проверки (проверка не показана выше для упрощения) как Form1 не только получает уведомление о том, что кнопка была нажата, но также отправляет строку, которая находится внутри LeftSide_D ata?
  • как показать событие LeftSide всем, кто хочет подписаться? Это ключевое слово "делегат" или ключевое слово "событие"? или что-то другое? слишком много ключевых слов на основе событий и, следовательно, основной источник путаницы.
  • следует изменить private void LeftSide_Button_Click(object sender, EventArgs e) с возврата void на private Eventhandler LeftSide_Button_Click(object sender, EventArgs e), и если да, то что я возвращаю ... что такое EventHandler " сделано из "?

EDIT: Я нашел следующую диаграмму, и, хотя она не передает данные вместе с событием, реализует ли это шаг в правильном направлении?" введите описание изображения здесь

1 Ответ

1 голос
/ 13 июля 2020

Вы можете объявить делегата, который представляет подпись вашего настраиваемого события, предоставив любое количество параметров, которые вы хотите передать. Затем вы просто объявляете событие этого типа делегата. Кто угодно может подписаться на ваше настраиваемое событие, чтобы получать уведомления о его возникновении.

Вот простой пример с делегатом с именем dlgLeftSideData и событием с именем LeftSideData. Он передает отправителя (экземпляр LeftSide, создающий событие), а также строковые данные. Существует также свойство publi c, доступное только для чтения, к которому при желании можно получить доступ через отправителя. Я подключил событие нажатия кнопки для «проверки», а затем оно вызывает настраиваемое событие, если есть подписчики:

class LeftSide
{

    public event dlgLeftSideData LeftSideData;
    public delegate void dlgLeftSideData(LeftSide sender, string data);
    
    private Panel LeftSide_Panel = new Panel();
    private TextBox LeftSide_TextBox = new TextBox();
    private Button LeftSide_Button = new Button();

    public LeftSide()
    {
        LeftSide_TextBox.Location = new Point(5, 5);
        LeftSide_Button.Location = new Point(5, 25);            
        LeftSide_Panel.Controls.Add(LeftSide_TextBox);
        LeftSide_Panel.Controls.Add(LeftSide_Button);

        LeftSide_Button.Click += LeftSide_Button_Click;
    }

    private void LeftSide_Button_Click(object sender, EventArgs e)
    {
        if (true) // some kind of validation
        {
            LeftSideData?.Invoke(this, this.Data); // raise the event if there are any subscribers
        }
    }

    public string Data
    {
        get
        {
            return LeftSide_TextBox.Text;
        }
    }
    
    public Panel LeftSidePanel
    {
        get {
            return this.LeftSide_Panel;
        }                        
    }

}

Вот пример кода в Form1, который подписывается на настраиваемое событие и что-то делает с полученными данными:

public partial class Form1 : Form
{

    LeftSide ls = new LeftSide();

    public Form1()
    {
        InitializeComponent();
        this.Controls.Add(ls.LeftSidePanel);
        ls.LeftSideData += Ls_LeftSideData;
    }

    private void Ls_LeftSideData(LeftSide sender, string data)
    {
        label1.Text = data;
        // or we could use "sender" somehow as well
        label1.Text = sender.Data; // get value from the read-only property
    }

}

Вы можете создать свойство или метод в своих классах, которые получают ссылку на другой LeftSide / RightSide и внутренне подписываются на события.

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