Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Observer implementation

I want a button that when it's pushed a new string is shown in the textboxes.

What am I doing wrong?

Can someone enlighten me? Why doesn't this code work?

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        public event Startdelegate StartEvent;
        myButton button;
        newTb[] tb;
        public Form1()
        {
            InitializeComponent();

            button = new myButton();
            button.Parent = this;
            button.Location = new Point(120, 0);
            button.Text = "click on me!!!";
            tb = new newTb[8];

            for (int i = 0; i <= 80; i += 15)
            {
                tb[i / 15] = new newTb();
                tb[i / 15].Parent = this;
                tb[i / 15].Location = new Point(i + i, i + i);
               // button.Subscribe(tb[i / 15]);
            }

            button.Click += new EventHandler(button_Click);

        }
        private void button_Click(object sender, EventArgs e)
        {
            button.s = "this is clicking";
            //button.Notify();
        }
    }

    public class myButton : Button, IObservable<newTb>
    {
        public string s;
        private List<IObserver<newTb>> observers;

        public myButton()
        {
            observers = new List<IObserver<newTb>>();
        }

        public IDisposable Subscribe(IObserver<newTb> observer)
        {
            if (!observers.Contains(observer))
            {
                observers.Add(observer);           
            }
            return new Unsubscriber(observers, observer);  
        }

        protected void Notify(newTb tb)
        {
            foreach (IObserver<newTb> observer in observers)
            {
                observer.OnNext(tb);
            }
        }

        #region Unsubscriber
        private class Unsubscriber : IDisposable
        {
            private List<IObserver<newTb>> observers;
            private IObserver<newTb> observer;

            public Unsubscriber(List<IObserver<newTb>> observers, IObserver<newTb> observer)
            {
                this.observers = observers;
                this.observer = observer;
            }

            public void Dispose()
            {
                if (observer != null && observers.Contains(observer))
                {
                    observers.Remove(observer);
                }
            }
        }
        #endregion 

        class newTb : TextBox, IObserver<string>
        {
            string s;
            public void OnCompleted() { }
            public void OnError(Exception error) { }
            public void OnNext(string value)
            {
                this.Text = value;
            }
        }
    }
}
like image 734
yoav.str Avatar asked Sep 07 '10 01:09

yoav.str


2 Answers

According to http://msdn.microsoft.com/en-us/library/dd783449.aspx

The IObserver and IObservable interfaces provide a generalized mechanism for push-based notification, also known as the observer design pattern. The IObservable interface represents the class that sends notifications (the provider); the IObserver interface represents the class that receives them (the observer).

T represents the class that provides the notification information.

In your case the information you pass is a message (a string). In your sample you were passing the control newTB

With the following declaration

   public class ObservableButton : Button,  IObservable<string>   {}
   public class ObserverTextBox  : TextBox, IObserver<string>     {}

Every thing fall into places.

The method Notify of the classObservableButton can be written this way.

    public void Notify(string text)
    {
        foreach (IObserver<string> observer in _Observers)
        {                
            observer.OnNext(text);
        }
    }

Here the full source code

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace ObservableDemo
{
    public class ObservableButton : Button, IObservable<string>
    {
        private List<IObserver<string>> _Observers;

        public ObservableButton()
        {
            _Observers = new List<IObserver<string>>();
        }
        IDisposable IObservable<string>.Subscribe(IObserver<string> observer)
        {
            if (!_Observers.Contains(observer))
            {
                _Observers.Add(observer);
            }
            return new Unsubscriber(_Observers, observer);
        }
        public void Notify(string text)
        {
            foreach (IObserver<string> observer in _Observers)
            {                
                observer.OnNext(text);
            }
        }
        private class Unsubscriber : IDisposable
        {
            private List<IObserver<string>>     observers;
            private IObserver<string>           observer;

            public Unsubscriber(List<IObserver<string>> observers, IObserver<string> observer)
            {
                this.observers = observers;
                this.observer  = observer;
            }
            public void Dispose()
            {
                if (observer != null && observers.Contains(observer))
                {
                    observers.Remove(observer);
                }
            }
        }
    }
}

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace ObservableDemo
{    
    public class ObserverTextBox : TextBox,  IObserver<string>
    {
        private IDisposable unsubscriber;

        void IObserver<string>.OnCompleted()
        {
        }
        void IObserver<string>.OnError(Exception error)
        {

        }
        void IObserver<string>.OnNext(string value)
        {
            this.Text = value;
            this.Refresh();
        }
        public virtual void Subscribe(IObservable<string> provider)
        {
            if (provider != null)
                unsubscriber = provider.Subscribe(this);
        }
        public virtual void Unsubscribe()
        {
            unsubscriber.Dispose();
        }
    }    
}

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace ObservableDemo
{
    public partial class Form1 : Form
    {
        ObservableButton button;

        public Form1()
        {
            InitializeComponent();

            button          = new ObservableButton();
            button.Parent   = this;
            button.Location = new Point(120, 0);
            button.Text     = "click on me!!!";
            button.Click   += new EventHandler(button_Click);

            for (int i = 0; i < 8; i++)
            {
                ObserverTextBox tb  = new ObserverTextBox();
                tb.Parent           = this;
                tb.Location         = new Point(0 , 30+(i*30));
                tb.Width            = 300;
                tb.Subscribe(button);
            }
        }
        private void button_Click(object sender, EventArgs e)
        {
            button.Notify(String.Format("{0} this is the message", DateTime.Now));
        }
        void Form1_Load(object sender, System.EventArgs e)
        {
        }
    }
}
like image 107
Frederic Torres Avatar answered Dec 07 '22 10:12

Frederic Torres


I believe this could be your problem:

class newTb : TextBox, IObserver<string>

Because what you what you wanted to observe based on this sample:

observers = new List<IObserver<newTb>>();

is actually IObserver<newTb>, which is different type than IObserver<string>. Your newTb class does not implement first interface, it only implements the latter. Not sure why this compiles (if it does), though.

like image 22
Paweł Dyda Avatar answered Dec 07 '22 09:12

Paweł Dyda