#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(«Игра»), как указано в комментарии ниже (еще раз спасибо).