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

如何实现ERP系统中Form1与Form2间的数据共享及ToolStrip跨窗体操作?

解决ERP系统主窗体ToolStrip跨子窗体数据保存问题

以下是几种实用的实现方案,可根据你的系统复杂度选择:


方案1:数据模型+委托事件(低耦合,推荐)

步骤1:定义数据实体类

先抽象子窗体的输入数据为实体类,作为窗体间的数据传递载体:

public class Product
{
    public string ProductName { get; set; }
    public decimal Price { get; set; }
    // 对应Form2的其他输入字段
}

步骤2:子窗体Form2暴露操作方法与事件

在Form2中封装数据获取、保存逻辑,并定义事件通知主窗体保存结果:

public partial class Form2 : Form
{
    // 公开获取输入数据的方法
    public Product GetInputData()
    {
        return new Product
        {
            ProductName = txtProductName.Text.Trim(),
            Price = decimal.TryParse(txtPrice.Text, out var price) ? price : 0
        };
    }

    // 定义保存完成事件,通知主窗体结果
    public event EventHandler<bool> SaveFinished;

    // 内部数据库保存逻辑
    private bool SaveToDb(Product data)
    {
        try
        {
            // 示例:用EF Core保存
            using (var db = new ErpDbContext())
            {
                db.Products.Add(data);
                db.SaveChanges();
                return true;
            }
        }
        catch (Exception ex)
        {
            // 异常日志记录
            return false;
        }
    }

    // 供主窗体调用的公开保存方法
    public void ExecuteSave()
    {
        var inputData = GetInputData();
        bool success = SaveToDb(inputData);
        SaveFinished?.Invoke(this, success);
    }
}

步骤3:主窗体Form1绑定ToolStrip事件

在Form1中跟踪子窗体实例,点击保存按钮时触发子窗体的保存操作:

public partial class Form1 : Form
{
    private Form2 _activeEditForm;

    // 新增按钮打开Form2
    private void tsBtnAdd_Click(object sender, EventArgs e)
    {
        _activeEditForm = new Form2();
        _activeEditForm.FormClosed += (s, args) => _activeEditForm = null;
        _activeEditForm.Show();
    }

    // 保存按钮触发子窗体保存
    private void tsBtnSave_Click(object sender, EventArgs e)
    {
        if (_activeEditForm != null && _activeEditForm.Visible)
        {
            _activeEditForm.ExecuteSave();
            // 订阅保存结果事件
            _activeEditForm.SaveFinished += (s, success) =>
            {
                MessageBox.Show(success ? "保存成功" : "保存失败");
                if (success)
                {
                    // 刷新主窗体数据列表等后续操作
                }
            };
        }
        else
        {
            MessageBox.Show("无活跃的编辑窗体");
        }
    }
}

方案2:接口标准化(高复用,适合多子窗体场景)

如果你的ToolStrip需要控制多个不同的子窗体,可通过接口统一操作规范:

步骤1:定义通用编辑窗体接口

public interface IEditableForm
{
    bool ValidateInput(); // 验证输入合法性
    object GetFormData(); // 获取输入数据
    bool SaveFormData(object data); // 保存数据
}

步骤2:子窗体实现接口

Form2实现上述接口,封装自身的验证、数据处理逻辑:

public partial class Form2 : Form, IEditableForm
{
    public bool ValidateInput()
    {
        if (string.IsNullOrWhiteSpace(txtProductName.Text))
        {
            MessageBox.Show("请输入产品名称");
            return false;
        }
        // 其他输入验证逻辑
        return true;
    }

    public object GetFormData()
    {
        return new Product
        {
            ProductName = txtProductName.Text.Trim(),
            Price = decimal.TryParse(txtPrice.Text, out var price) ? price : 0
        };
    }

    public bool SaveFormData(object data)
    {
        if (data is Product product)
        {
            try
            {
                using (var db = new ErpDbContext())
                {
                    db.Products.Add(product);
                    db.SaveChanges();
                    return true;
                }
            }
            catch
            {
                return false;
            }
        }
        return false;
    }
}

步骤3:主窗体ToolStrip通用化处理

主窗体无需跟踪具体子窗体实例,直接通过接口查找活跃窗体:

private void tsBtnSave_Click(object sender, EventArgs e)
{
    var activeForm = Application.OpenForms.OfType<IEditableForm>().FirstOrDefault(f => f.Visible);
    if (activeForm != null)
    {
        if (activeForm.ValidateInput())
        {
            var data = activeForm.GetFormData();
            bool success = activeForm.SaveFormData(data);
            MessageBox.Show(success ? "保存成功" : "保存失败");
            if (success)
            {
                // 刷新主界面数据
            }
        }
    }
    else
    {
        MessageBox.Show("无可保存的编辑窗体");
    }
}

注意事项

  • 避免直接在主窗体操作子窗体的控件,通过数据实体或接口解耦
  • 若ToolStrip需要全局复用,可将其封装为UserControl,暴露事件委托供宿主窗体绑定
  • 数据库操作建议封装为单独的服务层,避免窗体直接操作数据库

内容的提问来源于stack exchange,提问作者Jack C

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 13:22:03