2 Replies - 917 Views - Last Post: 15 April 2008 - 02:25 PM Rate Topic: -----

#1 killnine  Icon User is offline

  • D.I.C Head

Reputation: 19
  • View blog
  • Posts: 161
  • Joined: 12-February 07

Observer Design pattern and Interform Messaging

Posted 15 April 2008 - 07:10 AM

Hey guys,
I have been looking up some information on the Observer design pattern, but I dont really know if it applies to my application. Most of the examples I see paint it as a way to separate GUI elements from backend classes.

What I am wondering about is how to best keep track of an application's state if it contains two windows. Let me give an example:

I have a program with a main window that can spawn a second, graphing window. The second window can start and stop graphing, but there is also a button on the main window to start and stop graphing.

The issue is, I need to keep both forms on the same state. If I click "Start Graphing" on the main window, it had better start the graphing procedure on the second, and change the button on the second window to reflect that graphing has been initialized (usually by changing the button text to "Stop Graphing").

Communicating between two forms is a common problem. But I don't just want data to be passed from one form to another, I want the state-machine between two forms to be synchronized, if that makes sense.

Is This A Good Question/Topic? 0
  • +

Replies To: Observer Design pattern and Interform Messaging

#2 baavgai  Icon User is offline

  • Dreaming Coder
  • member icon

Reputation: 5801
  • View blog
  • Posts: 12,638
  • Joined: 16-October 07

Re: Observer Design pattern and Interform Messaging

Posted 15 April 2008 - 08:07 AM

There is an implicit design pattern in C# that's superior to the Observer in every way. It's the event model and it's a major strength of the language. I've always meant to write a tutorial on this, actually. It's more fun to write code. :P

Rather that kill myself explaining, here's some code.

Form1.cs
public partial class Form1 : Form {
	private Form2 childForm = null;
	public Form1() {
		InitializeComponent();
		ButtonStateInit();
	}
	
	private void ButtonStateInit() {
		this.bInvoke.Enabled = true;
		// we have no start and stop when no child form
		this.bStart.Enabled = false;
		this.bStop.Enabled = false;
	}

	private void bInvoke_Click(object sender, EventArgs e) {
		// dont ivoke twice.
		this.bInvoke.Enabled = false;
		childForm = new Form2();
		// listen to standard close event, for button reset
		childForm.FormClosed += new FormClosedEventHandler(childForm_FormClosed);
		
		// listen to custom event, for state change
		childForm.RunningStateChanged += new Form2.RunningStateChangedHandler(childForm_RunningStateChanged);
		
		// show the form
		childForm.Show();
	}

	void childForm_FormClosed(object sender, FormClosedEventArgs e) {
		// closed, but the buttons back
		ButtonStateInit();
	}

	void childForm_RunningStateChanged(object sender, EventArgs e) {
		// not using my object var (childForm) for this, we often don't have one
		// so this is how it's usually done
		Form2 frm = (Form2)sender;
		// look at the form state, update my buttons
		this.bStop.Enabled = frm.RunningState;
		this.bStart.Enabled = !this.bStop.Enabled;
	}

	private void bStop_Click(object sender, EventArgs e) {
		// tell the child, the child with then tell me and I'll update the buttons
		childForm.RunningState = false;
	}
	private void bStart_Click(object sender, EventArgs e) {
		// tell the child, the child with then tell me and I'll update the buttons
		childForm.RunningState = true;
	}
}



Form2.cs
public partial class Form2 : Form {
	public Form2() {
		InitializeComponent();
	}

	// set up an event, we need a delegate
	public delegate void RunningStateChangedHandler(object sender, EventArgs e);
	// an the event itself
	public event RunningStateChangedHandler RunningStateChanged;

	// a nice public property, so outside forces can mess with our state
	public bool RunningState {
		get {
			return this.bStop.Enabled;
		}
		set {
			// nothing to do
			if (this.bStop.Enabled && value) { return; }
			this.bStop.Enabled = value;
			this.bStart.Enabled = !this.bStop.Enabled;
			// do something
			//...
			// tell listeners
			if (this.RunningStateChanged != null) {
				// we have listeners, fire an event
				RunningStateChanged(this, new EventArgs());
			}
		}
	}

	// buttons call our own property
	private void bStop_Click(object sender, EventArgs e) {
		RunningState = false;
	}
	private void bStart_Click(object sender, EventArgs e) {
		RunningState = true;
	}

	// on load, set a false state
	private void Form2_Load(object sender, EventArgs e) {
		this.RunningState = false;
	}
}



I know it's a lot to chew on. I'll get the tutorial done sometime. Until then, hope this helps.

This post has been edited by baavgai: 15 April 2008 - 08:08 AM

Was This Post Helpful? 0
  • +
  • -

#3 killnine  Icon User is offline

  • D.I.C Head

Reputation: 19
  • View blog
  • Posts: 161
  • Joined: 12-February 07

Re: Observer Design pattern and Interform Messaging

Posted 15 April 2008 - 02:25 PM

View Postbaavgai, on 15 Apr, 2008 - 08:07 AM, said:

There is an implicit design pattern in C# that's superior to the Observer in every way. It's the event model and it's a major strength of the language. I've always meant to write a tutorial on this, actually. It's more fun to write code. :P

Rather that kill myself explaining, here's some code.

Form1.cs
public partial class Form1 : Form {
	private Form2 childForm = null;
	public Form1() {
		InitializeComponent();
		ButtonStateInit();
	}
	
	private void ButtonStateInit() {
		this.bInvoke.Enabled = true;
		// we have no start and stop when no child form
		this.bStart.Enabled = false;
		this.bStop.Enabled = false;
	}

	private void bInvoke_Click(object sender, EventArgs e) {
		// dont ivoke twice.
		this.bInvoke.Enabled = false;
		childForm = new Form2();
		// listen to standard close event, for button reset
		childForm.FormClosed += new FormClosedEventHandler(childForm_FormClosed);
		
		// listen to custom event, for state change
		childForm.RunningStateChanged += new Form2.RunningStateChangedHandler(childForm_RunningStateChanged);
		
		// show the form
		childForm.Show();
	}

	void childForm_FormClosed(object sender, FormClosedEventArgs e) {
		// closed, but the buttons back
		ButtonStateInit();
	}

	void childForm_RunningStateChanged(object sender, EventArgs e) {
		// not using my object var (childForm) for this, we often don't have one
		// so this is how it's usually done
		Form2 frm = (Form2)sender;
		// look at the form state, update my buttons
		this.bStop.Enabled = frm.RunningState;
		this.bStart.Enabled = !this.bStop.Enabled;
	}

	private void bStop_Click(object sender, EventArgs e) {
		// tell the child, the child with then tell me and I'll update the buttons
		childForm.RunningState = false;
	}
	private void bStart_Click(object sender, EventArgs e) {
		// tell the child, the child with then tell me and I'll update the buttons
		childForm.RunningState = true;
	}
}



Form2.cs
public partial class Form2 : Form {
	public Form2() {
		InitializeComponent();
	}

	// set up an event, we need a delegate
	public delegate void RunningStateChangedHandler(object sender, EventArgs e);
	// an the event itself
	public event RunningStateChangedHandler RunningStateChanged;

	// a nice public property, so outside forces can mess with our state
	public bool RunningState {
		get {
			return this.bStop.Enabled;
		}
		set {
			// nothing to do
			if (this.bStop.Enabled && value) { return; }
			this.bStop.Enabled = value;
			this.bStart.Enabled = !this.bStop.Enabled;
			// do something
			//...
			// tell listeners
			if (this.RunningStateChanged != null) {
				// we have listeners, fire an event
				RunningStateChanged(this, new EventArgs());
			}
		}
	}

	// buttons call our own property
	private void bStop_Click(object sender, EventArgs e) {
		RunningState = false;
	}
	private void bStart_Click(object sender, EventArgs e) {
		RunningState = true;
	}

	// on load, set a false state
	private void Form2_Load(object sender, EventArgs e) {
		this.RunningState = false;
	}
}



I know it's a lot to chew on. I'll get the tutorial done sometime. Until then, hope this helps.


That's a great example. Very straightforward, I think. I am going to hold off for a few days to implement this, but I think that your code really laid the groundwork well. Thanks again.
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1