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

C#中如何从其他窗体调用多个窗体的UpdateTheme方法

最佳实现方案:统一调用所有派生窗体的UpdateTheme方法

这个问题其实很常见,核心就是要找到可靠的方式追踪所有继承自CustomForm的窗体实例,然后统一触发主题更新逻辑。我给你两种常用的最佳实现方式,你可以根据项目场景选择:


方案1:静态集合管理窗体实例(简单直接)

这种方式通过在基类中维护一个静态集合,自动追踪所有CustomForm的实例,后续直接遍历集合调用方法即可。

修改基类CustomForm

public abstract class CustomForm : Form
{
    // 静态集合存储所有活跃的CustomForm实例
    private static readonly List<CustomForm> _allFormInstances = new List<CustomForm>();
    // 对外提供只读访问,避免外部修改集合
    public static IReadOnlyCollection<CustomForm> AllInstances => _allFormInstances.AsReadOnly();

    protected CustomForm()
    {
        // 窗体创建时加入集合,加锁保证线程安全
        lock (_allFormInstances)
        {
            _allFormInstances.Add(this);
        }
    }

    protected override void Dispose(bool disposing)
    {
        if (disposing)
        {
            // 窗体销毁时从集合移除,防止内存泄漏
            lock (_allFormInstances)
            {
                _allFormInstances.Remove(this);
            }
        }
        base.Dispose(disposing);
    }

    public void UpdateTheme(string theme)
    {
        // 确保在UI线程执行,避免跨线程操作控件报错
        if (this.InvokeRequired)
        {
            this.Invoke(new Action<string>(UpdateTheme), theme);
            return;
        }

        if (theme == "dark")
        {
            this.BackColor = Color.Black;
        }
        else if (theme == "light")
        {
            this.BackColor = Color.White;
        }
    }
}

在Settings窗体中调用

public void btnSetThemeToDark_Click(object sender, EventArgs e)
{
    // 遍历所有活跃的CustomForm实例,调用主题更新方法
    foreach (var form in CustomForm.AllInstances)
    {
        form.UpdateTheme("dark");
    }
}

优缺点:

  • 优点:实现简单,逻辑直观,不需要额外的依赖管理
  • 缺点:基类和实例存在静态依赖,必须确保Dispose方法正确执行以避免内存泄漏

方案2:事件驱动解耦(低耦合推荐)

这种方式通过事件通知机制,让所有CustomForm实例主动订阅主题变更事件,Settings窗体只负责触发事件,不需要知道具体有哪些窗体存在。

改造Settings窗体

public partial class SettingsForm : Form
{
    // 定义主题变更事件,传递主题字符串参数
    public event Action<string> ThemeChanged;

    private void btnSetThemeToDark_Click(object sender, EventArgs e)
    {
        // 触发事件,通知所有订阅者更新主题
        ThemeChanged?.Invoke("dark");
    }

    private void btnSetThemeToLight_Click(object sender, EventArgs e)
    {
        ThemeChanged?.Invoke("light");
    }
}

修改基类CustomForm订阅事件

public abstract class CustomForm : Form
{
    // 假设Settings窗体是全局单例,或者通过构造函数传入
    private readonly SettingsForm _settingsForm;

    protected CustomForm(SettingsForm settingsForm)
    {
        _settingsForm = settingsForm;
        // 订阅主题变更事件
        _settingsForm.ThemeChanged += OnThemeChanged;
    }

    protected override void Dispose(bool disposing)
    {
        if (disposing)
        {
            // 取消订阅,避免内存泄漏
            _settingsForm.ThemeChanged -= OnThemeChanged;
        }
        base.Dispose(disposing);
    }

    private void OnThemeChanged(string theme)
    {
        // 收到事件后调用自身的主题更新方法
        UpdateTheme(theme);
    }

    public void UpdateTheme(string theme)
    {
        if (this.InvokeRequired)
        {
            this.Invoke(new Action<string>(UpdateTheme), theme);
            return;
        }

        if (theme == "dark")
        {
            this.BackColor = Color.Black;
        }
        else if (theme == "light")
        {
            this.BackColor = Color.White;
        }
    }
}

如果Settings窗体是单例模式,也可以直接在基类中获取单例实例订阅:

protected CustomForm()
{
    SettingsForm.Instance.ThemeChanged += OnThemeChanged;
}

优缺点:

  • 优点:模块间耦合度极低,扩展性强,新增窗体无需修改Settings代码
  • 缺点:需要处理事件的订阅/取消逻辑,确保Settings窗体的实例可被所有CustomForm访问

选择建议

  • 如果项目规模较小、窗体数量不多,方案1足够好用,开发成本低
  • 如果项目复杂、需要更高的可维护性和扩展性,方案2是更优的选择

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 04:33:51