Когда у меня есть две нестатические формы, как сделать событие между ними - PullRequest
0 голосов
/ 01 января 2019

У меня есть две формы здесь, и я хочу вызвать функцию из одной в другую в c # winform.Я использую события, чтобы сделать это, но они не работают.Каждый раз, когда я вызываю changeTheme (), он выдает ошибку System.NullReferenceException: «Ссылка на объект не установлена ​​на экземпляр объекта.»

Я пытался вызвать ее через экземпляр формы Main_form, ноэто тоже не сработало.Я также попробовал события, но когда я добавил функцию, чтобы она снова стала нулевой.Но я бы хотел сделать это с событием.

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)))));
    }
}

Ответы [ 2 ]

0 голосов
/ 02 января 2019

Здесь я заметил одну большую проблему:

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

Вы создаете новый экземпляр Settings_form каждый раз, когда вызываете этот метод, но на самом деле вы никогда не делаете что-либос экземпляром - единственный раз, когда вы звоните Show(), это совершенно другой экземпляр:

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

Если вы хотите действовать Settings_form из своей основной формы, вы должны быть уверены, что вы всегдадействуя в том же экземпляре.

Кроме того, не забывайте подписываться и отписываться от событий таким образом, чтобы гарантировать, что вы случайно не столкнетесь с утечкой памяти.Подробнее об этом можно узнать здесь: Почему и как избежать утечек памяти в обработчике событий?

0 голосов
/ 02 января 2019

Исключение с нулевой ссылкой происходит из-за того, что ничто не подписано на ваше событие.

Обычно вы создаете событие, подобное этому:

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

В форме «Настройки_» вы можете просто зациклить все открытые формы и вызвать функцию 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);
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...