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> obse开发者_如何学Pythonrver 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.
精彩评论