У меня есть два UserControls, например LogInControl и CheckControl. Первоначально окно содержит LogInControl, а окно входа в систему изменяется после успешного входа в систему: окно содержит CheckControl.
Это код с MainWindow
public MainWindow()
{
InitializeComponent();
LogInControl logInControl = new LogInControl();
CheckControl checkControl = new CheckControl();
logInControl.OnSuccessfulLogin += (senser, e) =>
{
ChangeContentControl("Check");
};
checkInControl.LogOutClick += (senser, e) =>
{
ChangeContentControl("LogIn");
};
this.contentControl.Content = logInControl;
}
public void ChangeContentControl(string kindContentControl)
{
switch (kindContentControl)
{
case "LogIn":
{
...
this.contentControl.Content = new LogInControl();
}
break;
case "Check":
{
...
this.contentControl.Content = new CheckControl();
}
break;
}
}
Это код с LogInControl
public event EventHandler OnSuccessfulLogin;
private void loginButton_Click(object sender, RoutedEventArgs e)
{
OnSuccessfulLogin?.Invoke(this, e);
}
Работает корректно. Но «CheckControl» имеет кнопку «Выйти», при нажатии на эту кнопку в окне должно появиться содержимое «LogInControl». Но этого не случилось.
Это код с CheckControl
public event EventHandler LogOutClick;
private void logOutButton_Click(object sender, RoutedEventArgs e)
{
LogOutClick?.Invoke(this, e);
}
Отслеживание событий LogOutClick останавливается при переходе в окно с CheckInControl (LogOutClick становится пустым).
Не могу понять, почему так происходит. Помоги мне, пожалуйста.





Проблема, с которой вы сталкиваетесь, заключается в том, что, когда вы переключаете элементы управления, вы создаете новые. В новом не зарегистрированы события. Таким образом, вы перезаписываете предыдущее созданное с зарегистрированными событиями.
switch (kindContentControl)
{
case "LogIn":
{
...
this.contentControl.Content = new LogInControl(); <- here
^^^------------
}
break;
case "Check":
{
...
this.contentControl.Content = new CheckControl(); <- here
}
break;
}
ИСПРАВИТЬ: Вы должны назначить ранее созданные элементы управления:
Эти переменные должны быть полями, потому что вы хотите получить доступ к одному и тому же экземпляру разными методами:
private LogInControl logInControl = new LogInControl();
private CheckControl checkControl = new CheckControl();
и переключатель должен быть таким:
switch (kindContentControl)
{
case "LogIn":
{
...
this.contentControl.Content = this.logInControl;
}
break;
case "Check":
{
...
this.contentControl.Content = this.checkControl;
}
break;
}
вы создаете по 2 экземпляра каждого элемента управления. первый в конструкторе, и они подписаны на событие. второй в методе ChangeContentControl, и у них не есть подписка на события.
поэтому вы можете повторно использовать элементы управления, сохраняя их в локальной переменной
LogInControl logInControl = new LogInControl();
CheckControl checkControl = new CheckControl();
public MainWindow()
{
InitializeComponent();
logInControl.OnSuccessfulLogin += (senser, e) =>
{
ChangeContentControl("Check");
};
checkInControl.LogOutClick += (senser, e) =>
{
ChangeContentControl("LogIn");
};
this.contentControl.Content = logInControl;
}
public void ChangeContentControl(string kindContentControl)
{
switch (kindContentControl)
{
case "LogIn":
{
...
this.contentControl.Content = logInControl ;
}
break;
case "Check":
{
...
this.contentControl.Content = checkControl;
}
break;
}
}
или также подписаться на новые экземпляры на событие. Управление с подпиской создается отдельным методом во избежание дублирования кода
public MainWindow()
{
InitializeComponent();
this.contentControl.Content = getLogInControl();
}
private LogInControl getLogInControl()
{
LogInControl logInControl = new LogInControl();
logInControl.OnSuccessfulLogin += (senser, e) =>
{
ChangeContentControl("Check");
};
return logInControl;
}
private CheckControl getCheckControl()
{
CheckControl checkControl = new CheckControl();
checkControl.LogOutClick += (senser, e) =>
{
ChangeContentControl("LogIn");
};
return checkControl;
}
public void ChangeContentControl(string kindContentControl)
{
switch (kindContentControl)
{
case "LogIn":
{
...
this.contentControl.Content = getLogInControl();
}
break;
case "Check":
{
...
this.contentControl.Content = getCheckControl();
}
break;
}
}
1. Переместите подписку на событие
LogOutClickвнутри методаChangeContentControlили 2. Сделайте глобальное удаление окон и используйте один и тот же экземпляр везде.