我正在开发一个win form应用程序,我发现自己经常要求访问我的父表单中的方法,说Form1来自另一个类,无论是表单类还是只是一个类.我在表单1的构造函数中有一些初始化器,因此我无法创建Form1的实例.所以我无法访问Form1的方法.
所以我觉得这是一个不好的做法.但是,在某些情况下,我不知道还有什么可以做,例如考虑这种情况.我有一个名为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(“text”,Label1)一样调用它;
但是如果我从另一个类中调用它来引用Label1,我将需要一个Form1的实例,但是我将无法创建它,那么最佳做法是什么呢?
解决方法
我通常这样做的方式是让子窗体公开与该窗体上的逻辑操作和事件相对应的事件,例如:
/// <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等处理调用调用到正确线程的调用…而不是子表单 – 除非你在后台线程上工作,否则这将是不必要的.