2011-05-16 67 views
8

我正在开发一个win窗体应用程序,并且我发现自己经常需要访问父窗体中的方法,比如来自另一个窗体的Form1,上课或只是一堂课。我有我的表单1的构造函数中的一些初始化器,因此我无法创建Form1的实例。所以我无法访问Form1的方法。调用父窗体中的方法并访问父窗体中的gui元素的最佳实践#

所以我觉得这是一个不好的做法。但是,有些情况下我不知道还有什么可以考虑的情况。我有一个名为ProcessData的类,其中我有一个接收文件的方法,逐行读取并处理数据。现在我将这个方法作为我主窗体Form1中的一个线程调用。我的要求是我想要在主窗体Form1的多行文本框中显示当前正在处理的行的数据过程。

以前我做什么我都在同一Form1中拥有了一切,所以我用一个代表,像

delegate void SetTextCallback(string text, Control ctrl); 
private void SetText(string text, Control ctrl) 
    { 
     if (ctrl.InvokeRequired) 
     { 
      SetTextCallback d = new SetTextCallback(SetText); 
      this.Invoke(d, new object[] { text, ctrl }); 
     } 
     else 
     { 
      if (ctrl.GetType() == typeof(Label)) 
      { 
       ctrl.Text = text; 
      } 
      else 
      { 
       ctrl.Text += Environment.NewLine + text; 
      } 
     } 
    } 

,我调用此类似的setText(“文本”,Label1的);

但是如果我从另一个类中调用它来引用Label1我需要Form1的一个实例,但我无法创建它,那么最佳做法是什么?

(我知道我可以只通过文字的setText和处理控制那里,但我会用同样的事情为各种不同阶层调用文本框和标签控件)

+0

如果您使用的是WPF,命令将是一个不错的选择,但是......在任何情况下,孩子都应该“分离”或不需要父母的知识。这不仅仅是一个重用的事情,它使得错误更容易避免和修复。 – Jodrell 2011-05-16 11:52:47

+1

如果你真的不想使用事件,因为wahtever的原因。孩子应该声明委托类型并接受一个实例作为参数;父代可以实现代理并将实例传递给子代,则线程检查应该位于父代中。就像写你自己的事件一样。我不是在建议这个答案。 – Jodrell 2011-05-16 12:01:18

回答

6

,我通常做的方式是让孩子形式暴露对应于该表格上的逻辑动作和事件的事件,例如:

/// <summary> 
/// Occurrs when an item is selected in the form 
/// </summary> 
public event EventHandler<ItemSelectedEventArgs> ItemSelected; 

/// <summary> 
/// Fires the <see cref="ItemSelected" /> event 
/// </summary> 
protected void OnItemSelected(MyItem item) 
{ 
    var handler = this.ItemSelected; 
    if (handler != null) 
    { 
     ItemSelectedEventArgs args = new ItemSelectedEventArgs(); 
     args.Item = item; // For example 
     handler(this, args); 
    } 
} 

的想法是,你的父窗体的逻辑应该对你的孩子形式的行为做出反应,而不是在你的孩子形式上对父母形式的行为采取行动 - 你应该尽可能地封闭形式逻辑(又称分离关注点)。

此外,作为一种模式,它应该是通过InvokeRequired等处理将呼叫整理到正确线程的父/呼叫表单 - 而不是子表单 - 无论如何,除非您在背景上工作,否则这将是不必要的线程。

5

你的类应提高事件和你的表单应该有事件处理程序。这会将表单代码保存在您的表单中,并将您的类代码保存在您的类中。漂亮而整洁。

2

引发事件,如Kragen和理查德建议将工作,并停止为紧密耦合的父/子关系,但如果你想要的东西真的灵活,窥视Event Aggregator模式。在棱镜项目here中提供了一个不错的选择,尽管很多人觉得使用起来不方便,并且已经创建了扩展以便更容易地使用,例如this,或者从头开始编写,如this

基本上,这个想法是,父母甚至不关心该消息来自其子窗口。子窗口只是在消息总线上抛出诸如“Open Order#6”之类的消息,假设其他人会处理它,几乎与提出事件相同。在其他地方,负责包含所有子表单的父表单已订阅了“Open Order”消息,因此它接收到该消息,并为Order#6打开一个新的子窗口。

由于家长不再直接“与孩子焊接”,所以现在也可能将这些信息发送到其他地方。您可以从父表单本身最近使用的列表中提取“打开订单”消息,或者响应某个被点击的其他表单中的超链接。 要求打开订单#6不再重要,只有有人做过。这是一个非常灵活的模型,可以消除很多紧密耦合。

+0

这看起来很有趣,但对于我的范围,我认为我会与事件本身。我稍后再看看它。 – swordfish 2011-05-17 03:26:21

+0

是的,对于一个简单的例子,事件会很好。你最终会发现,连接所有不同的事件会变得很痛苦。一旦你使用聚合器,我恐怕没有回头路,我的意思是你会被迷住。同时,我建议您不要发出像grid1_SelectionChanged这样的特定事件。控制者,父母形式或任何“倾听”事件真的不需要那种细节。数据是否在网格或列表中真的不是它的问题。引发像OrderSelectionChanged这样的事件,隐藏它发生的事情。 – Mel 2011-05-17 12:22:36

相关问题