首页 > 解决方案 > 当我有两个非静态表单时,如何在它们之间进行事件

问题描述

我这里有两种形式,我想在 c# winform 中从一个到另一个调用该函数。我使用事件来做到这一点,但它们不起作用。每次我调用 changeTheme () 时,它都会抛出 System.NullReferenceException 错误:“对象引用未设置为对象的实例。”

我试图通过 Main_form 表单的实例给她打电话,但它也不起作用。我也尝试了这些事件,但是当我添加了一个函数来使其再次设置为 null 时。但我想用一个事件来做。

public delegate void statusChange();

public partial class Settings_form : Form
{
    public event statusChange changeTheme;

    //Here is some function, variables declaration and code

    private void UseDarkMode_chk_CheckedChanged(object sender, EventArgs e)
    {
        //Some code
        SettingsClass.UseDarkMode = this.UseDarkMode_chk.Checked;
        //if (changeTheme != null)
            changeTheme();
    }
}



public partial class Main_form : Form
{

    private void Form1_Load(object sender, EventArgs e)
    {

        callChangeTheme();
    }

    private void settingsToolStripMenuItem_Click(object sender, EventArgs e)
    {
        Settings_form settings_Form = new Settings_form();
        settings_Form.Show();
    }


    public void callChangeTheme()
    {
        Settings_form settings_Form = new Settings_form();
        settings_Form.changeTheme += new statusChange(chooseOtherTheme);
    }

    public void chooseOtherTheme()
    {
        if (SettingsClass.UseDarkMode)
            ToDarkMode();
        else ToLightMode();
    }

    public void ToDarkMode()
    {
        this.BackColor = Color.FromArgb(((int)(((byte)(28)))), ((int)(((byte)(28)))), ((int)(((byte)(28)))));
    }

    public void ToLightMode()
    {
         this.BackColor = Color.FromArgb(((int)(((byte)(241)))), ((int)(((byte)(241)))), ((int)(((byte)(241)))));
    }
}

标签: c#winformsevents

解决方案


发生空引用异常是因为没有订阅您的事件。

通常你会创建一个这样的事件:

public event EventHandler<EventArgs> MyEvent;

它比旧的事件/代表风格更容易阅读,但工作方式完全相同。

并像这样开火:

MyEvent?.Invoke(this, EventArgs.Empty);

这样,只有当您有订阅者时它才会触发。再次类似于 if != null fire 旧样式。

有了这个,有一种更简单的方法可以在没有事件的情况下实现你想要的。

如果您创建了一个派生表单并在那里实现了更改代码,您可以从中创建其余的表单,然后直接调用更改代码:

您的新基本形式:

public MyDerivedForm : Form
{
    public MyDerivedForm()
    {
        InitializeComponent();
    }

    public void ChangeTheme(bool usedarkmode)
    {
        if (usedarkmode)
            ToDarkMode();
        else
            ToLightMode();
    }

    public void ToDarkMode()
    {
        this.BackColor = Color.FromArgb(28, 28, 28);
    }

    public void ToLightMode()
    {
        this.BackColor = Color.FromArgb(241, 241, 241);
    }
}

我已经简化了您的 FromArgb 调用。你所有的演员都是完全多余的。

现在从 导出所有其他形式MyDerivedForm

public MainForm : MyDerivedForm
{
}

只需向项目添加一个新表单并将其更改: Form: MyDerivedForm

在您的 Settings_form 中,您可以遍历所有打开的表单并在每个表单上调用 ChangeTheme 函数,然后在明暗模式之间切换。

public Settings_form: MyDerivedForm
{
    public Settings_form()
    {
        InitializeComponent();
    }

    private void UseDarkMode_chk_CheckedChanged(object sender, EventArgs e)
    {
        //Some code
        SettingsClass.UseDarkMode = this.UseDarkMode_chk.Checked;

        foreach(MyDerivedForm form in Application.OpenForms.OfType<MyDerivedForm>())
        {
            form.ChangeTheme(SettingsClass.UseDarkMode);
        }
    }
}

推荐阅读