public ShellViewModel(GameService gameService, InteractivityService interactivityService, Dispatcher uiDispatcher)
        {
            _gameService          = gameService ?? throw new ArgumentNullException(nameof(gameService));
            _interactivityService = interactivityService ?? throw new ArgumentNullException(nameof(interactivityService));
            _uiDispatcher         = uiDispatcher ?? throw new ArgumentNullException(nameof(uiDispatcher));

            _mainViewModel = new CreateViewModel(_gameService, interactivityService, _uiDispatcher);
            _gameViewModel = new GameViewModel(_gameService, _uiDispatcher);

            _newCommand    = new SimpleCommand(Create, CanCreate);
            _saveCommand   = new SimpleCommand(Save, CanSave);
            _saveAsCommand = new SimpleCommand(SaveAs, CanSaveAs);
            _loadCommand   = new SimpleCommand <string>(Load, CanLoad);
            _exitCommand   = new SimpleCommand(Exit);

            _mainViewModel.Started += (s, e) => {
                SetCurrentGameFilePath(null);
                UpdateActiveViewModel();
            };
            _mainViewModel.Canceled += (s, e) => UpdateActiveViewModel();

            _gameViewModel.PropertyChanged += (s, e) => {
                _newCommand.RaiseCanExecuteChanged();
                _loadCommand.RaiseCanExecuteChanged();
                _saveCommand.RaiseCanExecuteChanged();
                _saveAsCommand.RaiseCanExecuteChanged();
            };

            _gameService.CurrentGameChanged += (s, e) => {
                // the service isn't expected to run the events on the main thread
                _uiDispatcher.Invoke(() => {
                    _saveCommand.RaiseCanExecuteChanged();
                    UpdateActiveViewModel();
                });
            };

            ActiveViewModel = _mainViewModel;
        }