Observer mode Practice - implement the value transfer between winform forms

Application of observer mode: Winform form pass value

The concept of observer pattern:

One to many dependencies between objects are defined so that when an object changes state, all its dependents will be notified and updated.

Today, we will learn to use the observer mode. First, imagine this scenario: when the values in one form (main form) change, the values in other forms will change accordingly. The simplest way to implement this is to create a common method in the subform class and an instance of the subform in the main window body. Calls the public method of the subform when the value changes. Another simple method is to use static attributes, equivalent to global variables, which can only be used for small applications. The first one has a disadvantage. When adding subforms, we need to change the code of the main form class. It is not possible to dynamically add and delete updates to values in subform classes. In this case, observer mode can be introduced.
We first create a winform project, add three forms frmMain, frmsub1 and frmsub2, and each form adds a textbox text box. When the value of the text box in the main form changes, the value of the other two subforms will change accordingly. Here we refer to Head First design pattern, and design publishers and subscribers first (I think it's more convenient here). The code is as follows:

 public interface ISubject
 {
     /// <summary>
     ///Registered subscribers
     /// </summary>
     /// <param name="observer"></param>
     void RegisterObserver(IObserver observer);

     /// <summary>
     ///Delete subscriber
     /// </summary>
     /// <param name="observer"></param>
     void RemoveObserver(IObserver observer);

     /// <summary>
     ///Notify subscribers
     /// </summary>
     void NotifyObservers();
 }

public interface IObserver
{
    /// <summary>
    ///Observer's response to publisher
    /// </summary>
    /// <param name="message"></param>
    void Update(string message);
}

Modify the FrmMain class to implement the issubject interface, and add the change event to the text box. The code is as follows:

public partial class FrmMain : Form, ISubject
{
    private string Message { get; set; }
    private List<IObserver> _observers = new List<IObserver>();


    public FrmMain()
    {
        InitializeComponent();
    }


    private void FrmMain_Load(object sender, EventArgs e)
    {
        FrmSub1 frmSub1 = new FrmSub1(this);
        FrmSub2 frmSub2 = new FrmSub2(this);
        frmSub1.Show();
        frmSub2.Show();
    }

    /// <summary>
    ///Text box change event, call notify subscriber method
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void txtMain_TextChanged(object sender, EventArgs e)
    {
        this.Message = txtMain.Text;
        NotifyObservers();
    }

    /// <summary>
    ///Registered subscribers
    /// </summary>
    /// <param name="observer"></param>
    public void RegisterObserver(IObserver observer)
    {
        _observers.Add(observer);
    }

    /// <summary>
    ///Remove subscribers
    /// </summary>
    /// <param name="observer"></param>
    public void RemoveObserver(IObserver observer)
    {
        _observers.Remove(observer);
    }

    /// <summary>
    ///Notify subscribers
    /// </summary>
    public void NotifyObservers()
    {
        foreach (IObserver observer in _observers)
        {
            observer.Update(Message);
        }
    }
}

The code of the subform class (subscriber) is as follows:

public partial class FrmSub1 : Form,IObserver
{
    public FrmSub1(ISubject subject)
    {
        InitializeComponent();
        //register
        subject.RegisterObserver(this);
    }
	//Methods that subscribers need to execute when publisher events occur
    public void Update(string message,bool isShown)
    {
       txtSub.Text = message;
    }
}

As you can see above, FrmMain relies on FrmSub1 and FrmSub2 again. Actually, it needs another method Show(). However, in order to show that the upper layer does not depend on the lower layer, we changed the code and added the judgment on whether the subform is shown in the NotifyObservers(bool isShown) method, so as to avoid FrmMain relying on FrmSub1 and FrmSub2
Code of FrmMain class:

public partial class FrmMain : Form, ISubject
{
    private string Message { get; set; }
    private List<IObserver> _observers = new List<IObserver>();


    public FrmMain()
    {
        InitializeComponent();
    }


    private void FrmMain_Load(object sender, EventArgs e)
    {
        //FrmSub1 frmSub1 = new FrmSub1(this);
        //FrmSub2 frmSub2 = new FrmSub2(this);
        //frmSub1.Show();
        //frmSub2.Show();
        //Here we use the method to get rid of the direct dependence on the subform
        NotifyObservers(false);
    }

    /// <summary>
    ///Text box change event, call notify subscriber method
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void txtMain_TextChanged(object sender, EventArgs e)
    {
        this.Message = txtMain.Text;
        NotifyObservers(true);
    }

    /// <summary>
    ///Registered subscribers
    /// </summary>
    /// <param name="observer"></param>
    public void RegisterObserver(IObserver observer)
    {
        _observers.Add(observer);
    }

    /// <summary>
    ///Remove subscribers
    /// </summary>
    /// <param name="observer"></param>
    public void RemoveObserver(IObserver observer)
    {
        _observers.Remove(observer);
    }

    /// <summary>
    ///Notify subscribers
    /// </summary>
    public void NotifyObservers(bool isShown)
    {

        foreach (IObserver observer in _observers)
        {
            observer.Update(Message,isShown);
        }
    }

}

Code for subform class:

public partial class FrmSub1 : Form,IObserver
{
    public FrmSub1(ISubject subject)
    {
        InitializeComponent();
        subject.RegisterObserver(this);
    }

    //The Update is changed here. isShown is true, indicating that the subform is displayed when the event is triggered
    public void Update(string message,bool isShown)
    {
        if (isShown)
        {
            txtSub.Text = message;
        }
        else
        {
            this.Show();
        }

    }
}
[STAThread]
static void Main()
{
    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);
    FrmMain frmMain = new FrmMain();
    FrmSub1 frmSub1 = new FrmSub1(frmMain);
    FrmSub2 frmSub2 = new FrmSub2(frmMain);
    Application.Run(frmMain);
}

Full source code reference: https://gitee.com/alexander 360/prodotnetdesignpatternframework45

122 original articles published, 20 praised, 140000 visitors+
Private letter follow

Posted on Sun, 12 Jan 2020 06:40:41 -0500 by lpxxfaintxx