快速回答
只需在辅助表单中添加对主要表单的引用:
public partial class TempCalib : Form
{
private MainForm _main
public TempCalib(MainForm main) : this()
{
_main = main;
}
/// Other stuffs
}
然后在构建辅助表单时分配值:
private TempCalib _tempCalib;
private void calibBtn_Click(object sender, EventArgs e)
{
if (_tempCalib == null)
_tempCalib = new TempCalib(this);
_tempCalib.Show();
}
如果calibBtn_Click
不在里面MainForm
(但它在里面UserControl
),那么您可以将_tempCalib
初始化替换为:
_tempCalib = new TempCalib((MainWindow)FindForm());
然后,您将能够调用主要表单:
private void OkButton_Click(object sender, EventArgs e)
{
_main.TempCommand();
this.Hide();
}
注意:这只是一个选项,您可以创建一个属性来保存MainForm
引用(因此可以重复使用辅助表单,并且对设计师更友好)而且TempCalib
不是一个,UserControl
而是一个Form
(非常原始,但对于一个UserControl
您可以检查它的父级)形成并将其转换为适当的类型)。
改进
这种引用通常是一种警告。通常 UI 组件不应该如此耦合,并且Form
经常执行某些事情的公共方法表明您的Form
. 如何改善这一点?
1. 解耦控制。那么第一步可能是将它们解耦一点,只需添加一个事件TempCalib
并使其MainForm
接收器:
public partial class TempCalib : Form
{
public event EventHandler SomethingMustBeDone;
private void OkButton_Click(object sender, EventArgs e)
{
OnSomethingMustBeDone(EventArgs.Empty); / TO DO
this.Hide();
}
}
然后在MainForm
:
private TempCalib _tempCalib;
private void calibBtn_Click(object sender, EventArgs e)
{
if (_tempCalib == null)
{
_tempCalib = new TempCalib();
_tempCalib.SomethingMustBeDone += _tempCalib_SomethingMustBeDone;
// In _tempCalib_SomethingMustBeDone you'll invoke proper member
// and possibly hide _tempCalib (remove it from OkButton_Click)
}
_tempCalib.Show();
}
2. 将逻辑与控件解耦。UI 经常更改,逻辑不会(并且当它更改时可能与 UI 不并行)。这只是第一步(现在TempCalib
不知道谁会使用它)。下一步(当表单内部发生太多事情时执行)是从表单本身中删除这种逻辑。小例子(非常原始),保持TempCalib
和以前一样(事件)并改变MainForm
为被动:
public partial class MainForm : Form
{
public event EventHandler Calibrate;
protected virtual void OnCalibrate(EventArgs e)
{
// TODO
}
}
现在让我们创建一个类来控制流程和逻辑:
public class MyTaskController
{
private MainForm _main;
private TempCalib _tempCalib;
public void Start()
{
_main = new MainForm();
_main.Calibrate += OnCalibrationRequested;
_main.Show(); // Or whatever else
}
private void OnCalibrationRequested(object sender, EventArgs e)
{
if (_tempCalib == null)
{
_tempCalib = new TempCalib();
_tempCalib.SomethingMustBeDone += OnSomethingMustBeDone();
}
_tempCalib.Show();
}
private OnSomethingMustBeDone(object sender, EventArgs e)
{
// Perform the task here then hide calibration window
_tempCalib.Hide();
}
}
是的,您需要编写更多代码,但这会将逻辑(例如,作为对操作的响应所做的事情)与 UI 本身分离。当程序长大时,这将帮助您根据需要更改 UI,使逻辑不知道这一点(并且在一个明确定义的地方)。我什至没有提到这将允许您使用不同的资源(人)来编写逻辑和 UI(或者为不同的 UI、WinForms 和 WPF重用逻辑)。无论如何,IMO 最明显且回报丰厚的好处是……可读性:您将始终知道逻辑在哪里以及 UI 管理在哪里,无需搜索,无需混淆,无需错误。
3. 将逻辑与实现解耦。同样,您还有更多步骤要执行(需要时)。您的控制器仍然知道具体类型(MainForm
和TempCalib
)。如果您需要在运行时选择不同的形式(例如,具有复杂的接口和简化的接口或使用依赖注入),则必须使用接口解耦控制器。只是一个例子:
public interface IUiWindow
{
void Show();
void Hide();
}
public interface IMainWindow : IUiWindow
{
event EventHandler Calibrate;
}
public interface ICalibrationWindow : IUiWindow
{
event EventHandler SomethingMustBeDone;
}