收录日期:2020/10/28 07:03:09 时间:2010-09-07 03:55:27 标签:design-patterns,c#-4.0

i want a button that when it's pushed a new string is showen in the textboxes

what am i doing wrong

can somone inlight me why doesnt this code works ? ...

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;
            }
        }
    }
}

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)
        {
        }
    }
}

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.