Создание кнопки NewGame с использованием WPF и MVVM

#c# #wpf #mvvm

#c# #wpf #mvvm

Вопрос:

Я «играю» с WPF и MVVM (цель: возможно, демонстрация со студентами в качестве альтернативы WinForms) с помощью C # и для таких целей построил тривиальную игру High-Low (угадай число и т. Д.) Я относительно новичок в C # и, следуя различным онлайн-урокам, имею рабочую «игру», за исключением команды для запуска новой игры из интерфейса. Мое решение kludge заключалось в том, чтобы добавить в код следующее, что в основном совпадает с повторным вызовом MainWindow():

 private void Restart_Click(object sender, RoutedEventArgs e)
        {
            InitializeComponent();
            Game = new HighLowGameViewModel();
            this.DataContext = Game;
        }
 

Но я хотел бы получить тот же эффект, используя ICommand в ViewModel.

Конструктор для виртуальной машины:

 public HighLowGameViewModel()
        {
            _game = new HighLowGameModel(1, 10);
            MakeGuessCommand = new HighLowViewGameGuessCommand(this);
            NewGameCommand = new HighLowViewGameNewGameCommand(this);
            
        }
 

MakeGuessCommand реализует ICommand и работает нормально, он находится в своем собственном классе, поскольку я пока избегаю использования таких вещей, как RelayCommand. Я создал новый класс для NewGameCommand на основе этого:

 private HighLowGameViewModel _viewModel;

        public HighLowViewGameNewGameCommand(HighLowGameViewModel viewModel)
        {
            _viewModel = viewModel;
        }

        #region ICommand Members
        public event EventHandler CanExecuteChanged
        {
            add { CommandManager.RequerySuggested  = value; }
            remove { CommandManager.RequerySuggested -= value; }
        }


        public bool CanExecute(object parameter)
        {
            return _viewModel.CanMakeNewGame;
        }

        public void Execute(object parameter)
        {
            _viewModel.NewGame();
        }
 

И _viewModel.NewGame():

 public void NewGame()
        {
            int currentMax = _game.Max;
            Debug.Write("I am trying to make  new game");
            _game = new HighLowGameModel(1, currentMax);
        }
 

Он запускает этот код при нажатии на кнопку в представлении, для команды которого установлено значение MakeNewCOmmand (Debug.Запишите выходные данные в окно вывода, и оно проходит через конструктор для HighLowGameModel и т. Д., Как При загрузке программы), НО ни одно из свойств для игры не обновляется в представлении.

Вероятно, я упускаю что-то глупое из-за своего незнания шаблона проектирования, но надеюсь, что я включил достаточно деталей, чтобы другие, возможно, показали мне, где я ошибаюсь ..? Как мне обновить приложение и вернуть его в исходное состояние?


Следующий комментарий от Клеменса (спасибо): добавление, _game объявленное как свойство в HighLowViewModel классе, содержит данные для игры (например, предположение пользователя, случайное значение, выбранное компьютером, количество оставшихся жизней и т. Д.). Каждый из них привязан к представлению через этот объект в ViewModel. Кажется, работает нормально, значения обновляются и отображаются, поскольку они привязаны к элементам управления в окне. Но при вызове команды для создания новой игры, которая, в свою очередь, вызывает конструктор для модели, устанавливающий новые значения (начальные значения) для игры:

 public HighLowGameModel Game
        {
            get { return _game; }
            set { 
                _game = value;
            }
        }

        #region Constructor
        public HighLowGameViewModel()
        {
            _game = new HighLowGameModel(1, 10);
            MakeGuessCommand = new HighLowViewGameGuessCommand(this);
            NewGameCommand = new HighLowViewGameNewGameCommand(this);
            
        }
        #endregion
 

Однако элементы в представлении не обновляются новыми значениями для начала игры.

Комментарии:

1. Неясно, что именно _game представляет собой элемент в HighLowGameViewModel и как представление связано с ним. Однако это должно быть общедоступное свойство с уведомлением об изменении для обновления пользовательского интерфейса. Уведомление об изменении означает, что класс-владелец реализует интерфейс INotifyPropertyChanged, а установщик свойства запускает событие PropertyChanged этого интерфейса.

2. Для справки см. Обзор привязки данных в WPF и Обзор источников привязки .

Ответ №1:


РЕШЕНИЕ:

Класс ViewModel, необходимый для реализации INotifyPropertyChanged, а также модель (… Я думаю, мне нужно еще подумать над этим, т.Е. Должна ли это быть только ViewModel, реализующая этот интерфейс, но это, похоже, приводит к дублированию …?). В любом случае, при вызове NewGame() в этом классе также необходимо указать OnPropertyChanged(«Игра»), как указано в комментарии ниже (еще раз спасибо).