好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

C#的WINFORM中子窗口传值给父窗口

在 WinForms 中实现子窗口向父窗口传值,可以通过多种方式实现。以下是 5 种常用方法及其详细步骤和示例代码,涵盖不同场景需求:

方法 1:通过公共属性(适合模态窗口)

场景:子窗口是模态窗口(ShowDialog()),父窗口等待子窗口关闭后直接获取值。

步骤:

子窗口定义公共属性:

public partial class ChildForm : Form

{

    public string ReturnValue { get; private set; } // 父窗口可读取的属性

    private void btnOK_Click(object sender, EventArgs e)

    {

        ReturnValue = txtInput.Text;

        this.DialogResult = DialogResult.OK; // 关闭窗口

    }

}

父窗口调用并获取值:

private void btnOpenChild_Click(object sender, EventArgs e)

{

    using (var childForm = new ChildForm())

    {

        if (childForm.ShowDialog() == DialogResult.OK)

        {

            string value = childForm.ReturnValue;

            lblResult.Text = $"接收的值:{value}";

        }

    }

}

方法 2:通过事件(适合非模态窗口)

场景:子窗口是非模态窗口(Show()),父窗口需要实时接收数据。

步骤:

子窗口定义事件:

public partial class ChildForm : Form

{

    // 定义事件委托

    public event Action<string> DataPassed;

    private void btnSend_Click(object sender, EventArgs e)

    {

        DataPassed?.Invoke(txtInput.Text); // 触发事件

    }

}

父窗口订阅事件:

private void btnOpenChild_Click(object sender, EventArgs e)

{

    var childForm = new ChildForm();

    childForm.DataPassed += (data) => 

    {

        // 确保在主线程更新 UI

        this.Invoke((MethodInvoker)delegate 

        {

            lblResult.Text = $"接收的值:{data}";

        });

    };

    childForm.Show(); // 非模态显示

}

方法 3:通过委托回调(解耦推荐)

场景:希望完全解耦父子窗口,通过回调传递数据。

步骤:

子窗口接收委托参数:

public partial class ChildForm : Form

{

    private readonly Action<string> _callback;

    // 构造函数接收回调委托

    public ChildForm(Action<string> callback)

    {

        InitializeComponent();

        _callback = callback;

    }

    private void btnOK_Click(object sender, EventArgs e)

    {

        _callback?.Invoke(txtInput.Text);

        this.Close();

    }

}

父窗口调用时传入回调:

private void btnOpenChild_Click(object sender, EventArgs e)

{

    var childForm = new ChildForm((data) => 

    {

        lblResult.Text = $"接收的值:{data}";

    });

    childForm.Show();

}

方法 4:通过父窗口引用(直接但耦合)

场景:快速实现,但父子窗口会紧密耦合。

步骤:

子窗口构造函数接收父窗口引用:

public partial class ChildForm : Form

{

    private readonly MainForm _parentForm;

    public ChildForm(MainForm parent)

    {

        InitializeComponent();

        _parentForm = parent;

    }

    private void btnSend_Click(object sender, EventArgs e)

    {

        _parentForm.UpdateLabel(txtInput.Text);

        this.Close();

    }

}

父窗口定义公共方法供子窗口调用:

public partial class MainForm : Form

{

    public void UpdateLabel(string text)

    {

        lblResult.Text = $"接收的值:{text}";

    }

    private void btnOpenChild_Click(object sender, EventArgs e)

    {

        var childForm = new ChildForm(this);

        childForm.Show();

    }

}

方法 5:使用静态类或单例(全局共享数据)

场景:多个窗口需要共享数据,但需谨慎使用以避免过度耦合。

步骤:

定义静态数据容器:

public static class DataContainer

{

    public static string SharedData { get; set; }

}

子窗口设置数据:

private void btnSave_Click(object sender, EventArgs e)

{

    DataContainer.SharedData = txtInput.Text;

    this.Close();

}

父窗口读取数据(如通过事件或定时检查):

private void btnOpenChild_Click(object sender, EventArgs e)

{

    var childForm = new ChildForm();

    childForm.FormClosed += (s, args) => 

    {

        lblResult.Text = $"接收的值:{DataContainer.SharedData}";

    };

    childForm.Show();

}

对比与选择

方法 优点 缺点 适用场景

公共属性 简单直接 仅适用于模态窗口 简单数据传递

事件 解耦,支持非模态窗口 需处理线程安全 实时数据更新

委托回调 高度解耦,灵活 需要预先定义回调逻辑 复杂交互或插件式架构

父窗口引用 快速实现 高耦合,不利于维护 快速原型开发

静态类 全局访问 数据共享可能导致混乱 小型应用或临时解决方案

最佳实践建议

解耦优先:优先使用 事件 或 委托回调,减少窗口间的直接依赖。

线程安全:非模态窗口传值时,使用 Control.Invoke 确保 UI 更新在主线程。

资源释放:非模态窗口及时注销事件,避免内存泄漏。

数据验证:在子窗口关闭前验证数据有效性,避免传递无效值。

通过以上方法,你可以根据具体需求选择最适合的子窗口传值方案。


查看更多关于C#的WINFORM中子窗口传值给父窗口的详细内容...

  阅读:17次