You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WinForms技术实践:将父窗体引用传入多子控件是否为良好实践?

优化子窗体与父窗体交互的实现方案

当前实现与问题

你当前通过子窗体基类持有父窗体的Form实例来实现交互,但存在两个核心问题:

  • 过度暴露:子窗体可访问父窗体所有公共成员,违反迪米特法则,耦合度高
  • 并发风险:多个子窗体同时操作父窗体时,易引发状态不一致或线程安全问题

以下是你的简化实现代码:

public partial class ParentForm : Form
{
    public ParentForm()
    {
        InitializeComponent();
    }

    private void Button1_OnClick(object sender, EventArgs e)
    {
        new ChildForm1(this).Show();
    }

    // Some other methods
}

public abstract partial class BaseChildForm : Form
{
    protected readonly Form _parent;

    public BaseChildForm(Form parent)
    {
        _parent = parent;
        InitializeComponent();
    }

    private void ThisForm_OnAppear(object sender, EventArgs e)
    {
        // Do some changes in the parent form through _parent field
    }

    // Some other methods as well
}

public partial class ChildForm1 : BaseChildForm
{
    public ChildForm1(Form parent) : base(parent){}

    // Overridden abstract methods and other methods
    // Do some tampering with the parent form
}

public partial class ChildForm2 : BaseChildForm
{
    public ChildForm2(Form parent) : base(parent){}

    // Overridden abstract methods and other methods
    // Do some tampering with the parent form
}

优化方案

1. 定义抽象接口限制交互范围

通过创建仅包含子窗体所需操作的接口,让父窗体实现该接口,子窗体仅依赖接口而非完整父窗体类型,缩小暴露范围。

实现代码:

// 定义仅包含子窗体需要的操作的接口
public interface IParentController
{
    void UpdateStatus(string status);
    bool IsUserLoggedIn { get; }
    void RefreshDataGrid();
}

// 父窗体实现接口
public partial class ParentForm : Form, IParentController
{
    public bool IsUserLoggedIn { get; private set; }

    public ParentForm()
    {
        InitializeComponent();
    }

    private void Button1_OnClick(object sender, EventArgs e)
    {
        new ChildForm1(this).Show();
    }

    public void UpdateStatus(string status)
    {
        lblStatus.Text = status;
    }

    public void RefreshDataGrid()
    {
        dataGridView1.DataSource = GetUpdatedData();
    }

    private object GetUpdatedData()
    {
        // 业务逻辑实现
        return new object();
    }
}

// 修改子窗体基类依赖接口
public abstract partial class BaseChildForm : Form
{
    protected readonly IParentController _parentController;

    public BaseChildForm(IParentController parentController)
    {
        _parentController = parentController;
        InitializeComponent();
    }

    private void ThisForm_OnAppear(object sender, EventArgs e)
    {
        _parentController.UpdateStatus("子窗体已打开");
    }
}

public partial class ChildForm1 : BaseChildForm
{
    public ChildForm1(IParentController parentController) : base(parentController){}

    public void DoOperation()
    {
        if (_parentController.IsUserLoggedIn)
        {
            _parentController.RefreshDataGrid();
        }
    }
}

优点:严格限制子窗体操作范围,降低耦合,符合面向接口编程原则,实现简单。


2. 使用事件机制解耦子父窗体

子窗体仅触发事件,父窗体自行订阅并处理逻辑,彻底解除子窗体对父窗体的直接依赖。

实现代码:

// 子窗体基类定义事件
public abstract partial class BaseChildForm : Form
{
    public class ParentActionEventArgs : EventArgs
    {
        public string StatusMessage { get; set; }
        public bool NeedRefreshData { get; set; }
    }

    public event EventHandler<ParentActionEventArgs> ParentActionRequested;

    protected virtual void OnParentActionRequested(ParentActionEventArgs e)
    {
        ParentActionRequested?.Invoke(this, e);
    }

    private void ThisForm_OnAppear(object sender, EventArgs e)
    {
        OnParentActionRequested(new ParentActionEventArgs
        {
            StatusMessage = "子窗体已打开",
            NeedRefreshData = false
        });
    }
}

public partial class ChildForm1 : BaseChildForm
{
    public void DoCriticalOperation()
    {
        OnParentActionRequested(new ParentActionEventArgs
        {
            StatusMessage = "操作完成,数据已更新",
            NeedRefreshData = true
        });
    }
}

// 父窗体订阅事件
public partial class ParentForm : Form
{
    public ParentForm()
    {
        InitializeComponent();
    }

    private void Button1_OnClick(object sender, EventArgs e)
    {
        var childForm = new ChildForm1();
        childForm.ParentActionRequested += ChildForm_ParentActionRequested;
        childForm.FormClosed += (s, args) => childForm.ParentActionRequested -= ChildForm_ParentActionRequested;
        childForm.Show();
    }

    private void ChildForm_ParentActionRequested(object sender, BaseChildForm.ParentActionEventArgs e)
    {
        lblStatus.Text = e.StatusMessage;
        if (e.NeedRefreshData)
        {
            dataGridView1.DataSource = GetUpdatedData();
        }
    }

    private object GetUpdatedData()
    {
        // 业务逻辑实现
        return new object();
    }
}

优点:子父窗体完全解耦,父窗体统一控制自身状态变更,避免多实例操作冲突。


3. 引入中介者模式(复杂场景适用)

如果存在多子窗体、复杂交互场景,可引入中介者类作为通信枢纽,所有窗体仅与中介者交互,避免形成复杂依赖网络。

实现代码:

// 中介者接口与实现
public interface IFormMediator
{
    void RegisterParent(ParentForm parent);
    void RegisterChild(BaseChildForm child);
    void RequestParentUpdate(string status, bool refreshData);
}

public class FormMediator : IFormMediator
{
    private ParentForm _parent;
    private List<BaseChildForm> _children = new List<BaseChildForm>();

    public void RegisterParent(ParentForm parent)
    {
        _parent = parent;
    }

    public void RegisterChild(BaseChildForm child)
    {
        _children.Add(child);
        child.FormClosed += (s, args) => _children.Remove(child);
    }

    public void RequestParentUpdate(string status, bool refreshData)
    {
        _parent.UpdateStatus(status);
        if (refreshData)
        {
            _parent.RefreshDataGrid();
        }
    }
}

// 父窗体依赖中介者
public partial class ParentForm : Form
{
    private readonly IFormMediator _mediator;

    public ParentForm(IFormMediator mediator)
    {
        _mediator = mediator;
        _mediator.RegisterParent(this);
        InitializeComponent();
    }

    private void Button1_OnClick(object sender, EventArgs e)
    {
        var childForm = new ChildForm1(_mediator);
        _mediator.RegisterChild(childForm);
        childForm.Show();
    }

    public void UpdateStatus(string status)
    {
        lblStatus.Text = status;
    }

    public void RefreshDataGrid()
    {
        dataGridView1.DataSource = GetUpdatedData();
    }

    private object GetUpdatedData()
    {
        // 业务逻辑实现
        return new object();
    }
}

// 子窗体依赖中介者
public abstract partial class BaseChildForm : Form
{
    protected readonly IFormMediator _mediator;

    public BaseChildForm(IFormMediator mediator)
    {
        _mediator = mediator;
        InitializeComponent();
    }

    private void ThisForm_OnAppear(object sender, EventArgs e)
    {
        _mediator.RequestParentUpdate("子窗体已打开", false);
    }
}

public partial class ChildForm1 : BaseChildForm
{
    public ChildForm1(IFormMediator mediator) : base(mediator){}

    public void DoOperation()
    {
        _mediator.RequestParentUpdate("操作完成", true);
    }
}

优点:集中管理交互逻辑,避免窗体间复杂依赖,便于扩展新场景。
缺点:增加额外类,简单场景下冗余。


内容的提问来源于stack exchange,提问作者Zombies are Real

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 10:40:06