我有三个名为frmBase(form1),frmGraph(form2)和frmBalloon(form3)的表单。
如果用户单击位于frmBase(form1)上的名为btnShow的按钮,则会打开frmGraph(form2)。
如果用户点击放置在frmGraph(form2)上的名为btnShow的按钮,则会打开frmBalloon(form3)。
现在,如果用户点击放在frmGraph(form2)上的名为btnCancel的按钮,或点击放在frmBalloon(form3)上的名为btnCancel的按钮,则除了frmBase(form1)之外,每个打开的表单都应该关闭。
因此,当用户单击form2或form3上的按钮时,除了mainform之外,每个表单都应该被关闭。那么有什么解决方案吗?
答案 0 :(得分:2)
维护需要在指定事件上关闭的所有表单对象的引用。在需要时在frmBase中创建并调用该函数。如果打开,该功能将负责关闭所有已注册的表格。
看起来像observer pattern个案例。
答案 1 :(得分:1)
这不是一个很好的解决方案,Application.OpenForms有点不可靠,但很容易:
public static void CloseAllFormsButMain() {
for (int ix = Application.OpenForms.Count - 1; ix > 0; --ix)
Application.OpenForms[ix].Close();
}
答案 2 :(得分:1)
观察者模式适用于某些特殊情况。此类场景的观察者模式的更专业版本是EventAggregator模式。事件聚合器模式非常适合此类场景。
简而言之,事件聚合器允许您集中发布/订阅事件。因此,所有订阅者和发布者仅与EventAggregator通信。订阅者订阅事件,发布者命令事件聚合器发布内容。
事件聚合器模式还将每个发布者订阅者彼此分离。这消除了子表单引用父表单的需要。
杰里米·米勒(Jeremy Miller)在他自己制造的驾驶室系列中提供了一个很好的例子。由于我的新会员资格,我无法发布指向网站的链接,只是搜索以下项目。
Martin Fowler的EventAggregator 由Jeremy Miller建立自己的CAB系列(codebetter.com) PRISM中的EventAggregator
这是一个使用C#和泛型编写的简单示例。这绝不是完整的。它只是为了说明一个简化的例子。有关更完整的模式转向Jeremy Millers的例子。
[代码]
//示例自定义事件参数 使用System;
命名空间EventAggregatorPatternDemo { public class CloseAllFormsEventArgs:EventArgs { } }
//示例表单代码 使用系统; 使用System.Collections.Generic; 使用System.ComponentModel; 使用System.Data; 使用System.Drawing; 使用System.Linq; 使用System.Text; 使用System.Windows.Forms;
命名空间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);
}
}
}
//事件聚合器代码 使用系统; 使用System.Collections.Generic;
命名空间EventAggregatorPatternDemo { 公共接口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);
}
}
}
}
}
} [/代码]
答案 3 :(得分:0)
您是否考虑过使用静态事件? Here就是一个简单的例子。