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

WinForms中如何从另一个窗体重新加载/初始化用户控件?

问题场景
  • 主窗体WindowMain点击「Roster」按钮后,在MainScreenPanel面板加载UserControlRoster用户控件
  • UserControlRoster包含DataGridView(显示人员花名册)和标签(如Name、Age),选中DataGridView行时标签填充对应数据
  • 点击Name标签弹出DialogEditWrestlerName窗体修改姓名,修改成功后需要刷新UserControlRoster使变更生效
  • 当前错误做法:保存时新建WindowMain实例,导致重复打开主窗体,而非刷新现有控件

现有代码片段:

主窗体加载用户控件代码

MainScreenPanel.Controls.Clear();
var uc = new UserControlRoster() { Dock = DockStyle.Fill };
MainScreenPanel.Controls.Add(uc);

UserControlRoster打开编辑窗体代码

wrestlerName = lblName.Text.ToString();

DialogEditWrestlerName EditWrestlerName = new DialogEditWrestlerName(wrestlerName);
EditWrestlerName.Show();

当前错误的保存代码(DialogEditWrestlerName中)

WindowMain Main = new WindowMain();
Main.Show(this);
this.Close();
解决方案

方法1:通过事件通知刷新(推荐,解耦各窗体)

在DialogEditWrestlerName中定义事件,保存成功时触发,让UserControlRoster订阅事件并执行刷新。

步骤1:在DialogEditWrestlerName中添加事件

public partial class DialogEditWrestlerName : Form
{
    // 定义保存成功事件
    public event Action OnNameSaved;

    public DialogEditWrestlerName(string wrestlerName)
    {
        InitializeComponent();
        // 初始化显示原姓名的逻辑
    }

    private void btnSave_Click(object sender, EventArgs e)
    {
        // 执行修改姓名的业务逻辑(已确认正常)
        
        // 触发事件通知外部刷新
        OnNameSaved?.Invoke();
        
        this.Close();
    }
}

步骤2:在UserControlRoster中订阅事件并刷新数据

修改打开编辑窗体的代码,同时新增刷新数据的方法:

public partial class UserControlRoster : UserControl
{
    public UserControlRoster()
    {
        InitializeComponent();
        LoadRosterData();
    }

    // 新增刷新数据方法
    public void LoadRosterData()
    {
        // 重新从数据源加载DataGridView数据
        // 示例:dataGridViewRoster.DataSource = GetLatestWrestlerList();
        // 若用BindingSource,可调用:((BindingSource)dataGridViewRoster.DataSource).ResetBindings(false);
    }

    private void lblName_Click(object sender, EventArgs e)
    {
        string wrestlerName = lblName.Text.ToString();
        DialogEditWrestlerName editForm = new DialogEditWrestlerName(wrestlerName);
        
        // 订阅保存成功事件
        editForm.OnNameSaved += () => 
        {
            LoadRosterData();
            // 可选:重新选中当前修改的行
        };
        
        editForm.ShowDialog(); // 模态对话框更适合编辑场景
    }
}

方法2:通过主窗体实例刷新

在DialogEditWrestlerName中找到已打开的WindowMain实例,调用主窗体的刷新方法重新加载控件。

步骤1:在WindowMain中添加刷新方法

public partial class WindowMain : Form
{
    public void RefreshRosterControl()
    {
        // 复用原加载控件的逻辑
        MainScreenPanel.Controls.Clear();
        var uc = new UserControlRoster() { Dock = DockStyle.Fill };
        MainScreenPanel.Controls.Add(uc);
    }

    // 原Roster按钮点击事件(保持不变)
    private void btnRoster_Click(object sender, EventArgs e)
    {
        RefreshRosterControl();
    }
}

步骤2:在DialogEditWrestlerName的保存按钮中调用主窗体方法

private void btnSave_Click(object sender, EventArgs e)
{
    // 执行修改姓名的业务逻辑
    
    // 查找当前打开的主窗体实例
    WindowMain mainForm = Application.OpenForms.OfType<WindowMain>().FirstOrDefault();
    if (mainForm != null)
    {
        mainForm.RefreshRosterControl();
    }
    
    this.Close();
}

方法3:直接刷新绑定数据源

如果UserControlRoster的DataGridView使用BindingSource绑定数据,可直接刷新数据源,无需重建控件:

public partial class UserControlRoster : UserControl
{
    private BindingSource _rosterBindingSource;

    public UserControlRoster()
    {
        InitializeComponent();
        _rosterBindingSource = new BindingSource();
        dataGridViewRoster.DataSource = _rosterBindingSource;
        LoadRosterData();
    }

    public void LoadRosterData()
    {
        var latestRoster = GetWrestlerListFromDataSource(); // 替换为你的数据源获取逻辑
        _rosterBindingSource.DataSource = latestRoster;
        // 若仅修改单条数据,可修改后调用:_rosterBindingSource.ResetBindings(false);
    }
}

后续通过事件或控件实例调用LoadRosterData即可完成刷新。


内容的提问来源于stack exchange,提问作者Braden Putt

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 10:52:37