Reputation: 4305
I have three forms named frmBase(form1),frmGraph(form2) and frmBalloon(form3).
frmGraph(form2) opens if the user clicks on the button named btnShow placed on frmBase(form1).
frmBalloon(form3) opens if the user clicks on the button named btnShow placed on frmGraph(form2).
Now if the user clicks on the button named btnCancel placed on the frmGraph(form2) OR clicks on the button named btnCancel placed on the frmBalloon(form3) every form that is open should be closed except frmBase(form1).
So, every forms should be closed except mainform when user clicks on the button placed on the form2 or form3. So for that is there any solution?
Upvotes: 0
Views: 669
Reputation: 43207
Maintain references of all form objects that needs to be closed on designated event. Create and Call the function in frmBase whenever needed. The function will be responsible to close all registered forms if open.
Looks like an observer pattern case.
Upvotes: 2
Reputation: 438
Observer pattern is appropriate with some specializaiton. A more specialized version of the observer pattern for this type of scenario is the EventAggregator pattern. The event aggregator pattern is ideal for this type of scenario.
In short the event aggregator allows you to centralize the publishing/subscription of events. Therefore all subscribers and publishers talk only to the EventAggregator. Subscribers subscribe to events and publishers command the event aggregator to publish something.
The event aggregator pattern also decouples each publisher subscriber from each other. This eliminates the need for the child forms to reference the parent forms.
Jeremy Miller provides a good example in his Build Your Own Cab series. Due to my new membership I cant post the links to the sites but just a do a search for the following items.
EventAggregator by Martin Fowler Build Your Own CAB series by Jeremy Miller (codebetter.com) EventAggregator in PRISM
Here is a simple example I cooked up using C# and generics. This is by no means complete. It is just to illustrate a simplified example. For a more complete patter turn to Jeremy Millers example.
[code]
//Sample Custom Event args using System;
namespace EventAggregatorPatternDemo { public class CloseAllFormsEventArgs : EventArgs { } }
//Sample Form 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 EventAggregatorPatternDemo { public partial class GraphForm : Form, IListener { public GraphForm() { InitializeComponent(); }
private void GraphForm_Load(object sender, EventArgs e)
{
EventAggregator.GetTheEventAggregator().Subscribe<CloseAllFormsEventArgs>(this);
}
public void Handle<TEventArgs>(TEventArgs e)
{
if (e.GetType() == typeof(CloseAllFormsEventArgs))
{
this.Close();
}
}
private void btnCloseAll_Click(object sender, EventArgs e)
{
EventAggregator.GetTheEventAggregator().Publish(this, new CloseAllFormsEventArgs());
}
private void GraphForm_FormClosed(object sender, FormClosedEventArgs e)
{
EventAggregator.GetTheEventAggregator().CancelSubscription<CloseAllFormsEventArgs>(this);
}
}
}
//Event Aggregator code using System; using System.Collections.Generic;
namespace EventAggregatorPatternDemo { public interface IListener { void Handle(TEventArgs e); }
public class EventAggregator
{
static EventAggregator _TheEventAggregator;
readonly Dictionary<Type, List<IListener>> _listeners;
private EventAggregator()
{
_listeners = new Dictionary<Type, List<IListener>>();
}
public static EventAggregator GetTheEventAggregator()
{
if(_TheEventAggregator == null)
{
_TheEventAggregator = new EventAggregator();
}
return _TheEventAggregator;
}
public void Publish<TEventArgs>(object sender, TEventArgs e)
{
if(_listeners.ContainsKey(e.GetType()))
{
var listOfSubscribers = _listeners[e.GetType()];
for(int i = listOfSubscribers.Count - 1; i > -1; i--)
{
listOfSubscribers[i].Handle(e);
}
}
}
public void Subscribe<TEventArgs>(IListener listener)
{
if(_listeners.ContainsKey(typeof(TEventArgs)))
{
_listeners[typeof(TEventArgs)].Add(listener);
}
else
{
List<IListener> newListenerList = new List<IListener>();
newListenerList.Add(listener);
_listeners.Add(typeof(TEventArgs), newListenerList);
}
}
//Cancels all subscriptions
public void CancelSubscription<TEventArgs>(IListener listener)
{
Type eventArgsType = typeof(TEventArgs);
if (_listeners.ContainsKey(eventArgsType))
{
//Remove from the end
for (int i = _listeners[eventArgsType].Count-1; i > -1; i-- )
{
//If the objects are the same
if(ReferenceEquals(_listeners[eventArgsType][i], listener))
{
_listeners[eventArgsType].RemoveAt(i);
}
}
}
}
}
} [/code]
Upvotes: 1
Reputation: 9726
Have you thought about using a static event? Here is a simple example.
Upvotes: 0
Reputation: 941465
It is not a great solution, Application.OpenForms is a bit unreliable, but easy:
public static void CloseAllFormsButMain() {
for (int ix = Application.OpenForms.Count - 1; ix > 0; --ix)
Application.OpenForms[ix].Close();
}
Upvotes: 1