EventHandler имеет значение NULL при запуске MVVM

Итак, я пытаюсь использовать общие переменные в своем приложении WPF. При этом я реализовал класс ViewModelController для хранения переменных, которые влияют на остальную часть моего приложения, используя eventhandler.

Мой класс ViewModelController таков:

    public class ViewModelController
    {

        private DataRowView _SelectedUniverse;

        public MenuViewModel MenuViewModel { get { return new MenuViewModel(this); } }

        public GamePageViewModel GamePageViewModel { get { return new GamePageViewModel(this); } }

        public PlayersViewModel PlayersViewModel { get { return new PlayersViewModel(this); } }

        public event EventHandler UniverseChanged;

        public DataRowView SelectedUniverse
        {
            get { return _SelectedUniverse; }
            set
            {
                _SelectedUniverse = value;
                UniverseChanged.Invoke(this, EventArgs.Empty);
                Debug.Print("Universe Changed in ViewModelController");
            }
        }

    }

Я тестирую это в своей модели меню ViewModel, чтобы узнать, переходит ли он в другой класс:

MenuViewModel

    public class MenuViewModel : ObservableObject
    {

        ViewModelController _ViewModelController;
        private DataView _Universes;
        private DataRowView _SelectedUniverse;

        public MenuViewModel(ViewModelController controller)
        {
            _ViewModelController = controller;
            _Universes = Controller.UniverseTableAdapter.GetData().DefaultView;
        }

        public DataView Universes
        {
            get { return _Universes; }
            set
            {
                _Universes = value;
                RaisePropertyChangedEvent("Universes");
            }
        }

        public DataRowView SelectedUniverse
        {
            get { return _SelectedUniverse; }
            set
            {
                _SelectedUniverse = value;
                Debug.Print("Universe Changed from Menu");
                _ViewModelController.SelectedUniverse = _SelectedUniverse;
                RaisePropertyChangedEvent("SelectedUniverse");
            }
        }
    }

PlayerViewModel Класс

public class PlayersViewModel : ObservableObject
{

    private ViewModelController _ViewModelController;

    #region Variables
    private ObservableCollection<Player> _Players = Controller.GetPlayers(0);
    private Player _SelectedPlayer;
    private DataView _Colleges = Controller.CollegeTableAdapter.GetData().DefaultView;
    private DataView _Universes = Controller.UniverseTableAdapter.GetData().DefaultView;

    private long _PlayerID;
    private string _PlayerFirstName;
    private string _PlayerLastName;
    private string _PlayerFullName;
    private DataRowView _SelectedCollege;
    private DataRowView _SelectedUniverse;
    private long _PlayerCollegeID;
    private long _UniverseID;
    private int _PlayerEnteredYear;

    private DataView _RegularSeasonStats = Controller.SeasonView.GetData().DefaultView;
    private DataRowView _SelectedSeason;
    private DataView _PlayoffStats = Controller.PlayoffsView.GetData().DefaultView;
    private DataView _PlayerSchedule = Controller.PlayerScheduleView.GetDataByPersonAndYear(0, 0).DefaultView;
    #endregion 

    public PlayersViewModel(ViewModelController controller)
    {
        _ViewModelController = controller;
        _ViewModelController.UniverseChanged += OnUniverseChanged;
        Debug.Print("PlayerViewModel Constructed");
    }

    public DataRowView SelectedUniverse
    {
        get { return _SelectedUniverse; }
        set
        {
            _SelectedUniverse = value;
            if (_SelectedUniverse != null)
            {
                _UniverseID = _SelectedUniverse.Row.Field<long>("UniverseID");
                RaisePropertyChangedEvent("SelectedUniverse");
            }
        }
    }

    private void OnUniverseChanged(object sender, EventArgs e)
    {
        SelectedUniverse = _ViewModelController.SelectedUniverse;
        Debug.Print("Universe was changed");
    }
}

Когда SelectedUniverse изменяется, он отправляет эту переменную в ViewModelController, который должен вызвать событие UniverseChanged. Однако я получаю Object Reference Not Set to an Instance of an Object.

Я знаю, что должен создать экземпляр EventHandler, но я не вижу способа создать его без конструктора. Могу я все сделать неправильно?

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
0
46
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

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

Перед вызовом вы должны проверить, есть ли слушатели. Как это:

public DataRowView SelectedUniverse
{
    get { return _SelectedUniverse; }
    set
    {
        _SelectedUniverse = value;
        UniverseChanged?.Invoke(this, EventArgs.Empty);
        // Or if you're using a C# version< 6:
        // var evtHandlers = UniverseChanged;
        // if (evtHandlers != null) evtHandlers.Invoke(this, EventArgs.Empty);
        Debug.Print("Universe Changed in ViewModelController");
    }
}

Я надеюсь, что это помогает.

Ваш код C# <6 должен сначала сохранить делегат в переменной, а затем работать с этой переменной вместо фактического делегата, чтобы избежать некоторых редких условий гонки.

Bradley Uffner 06.05.2018 17:42

@BradleyUffner Вы правы. Спасибо, что заметили это.

Diego Rafael Souza 06.05.2018 17:43

Пример здесь: codeblog.jonskeet.uk/2015/01/30/…

Bradley Uffner 06.05.2018 17:43

Так что это действительно помогает, хотя не запускает метод OnUniverseChanged в моем PlayersViewModel .... Я добавил к нему слушателя, не так ли?

jDave1984 07.05.2018 02:17

@ jDave1984 Я говорю об упомянутой вами ошибке Object Reference Not Set to an Instance of an Object. Класс PlayersViewModel (единственный, кто подписывается на указанное событие) никогда не вызывается (нет вызова get) в вашем коде (по крайней мере, в этом примере).

Diego Rafael Souza 07.05.2018 13:48

И я не вижу причин, по которым вы должны возвращать новый экземпляр этих объектов на каждом get.

Diego Rafael Souza 07.05.2018 13:54

Да, я сейчас занимаюсь рефакторингом. Однако get находится в моей привязке XAML, однако ... по-видимому, нет. Мне может понадобиться лучший и более эффективный способ переключения моделей просмотра и иметь некоторые общие переменные между ними.

jDave1984 08.05.2018 15:02

@ jDave1984 Итак, чем я могу вам помочь? Мой пост ответил на ваш вопрос?

Diego Rafael Souza 08.05.2018 15:09

Он ответил на мой первоначальный вопрос об ошибке Null, поэтому я доверяю вам ответ. Если вы можете помочь мне в чате или по электронной почте улучшить структуру, я был бы очень признателен

jDave1984 08.05.2018 22:38

@ jDave1984 Давай поговорим в чате, тогда.

Diego Rafael Souza 08.05.2018 22:46

Другие вопросы по теме