MVVM in WPF - How to alert ViewModel of changes in Model… or should I?

前端 未结 11 678
离开以前
离开以前 2020-11-27 09:51

I am going through some MVVM articles, primarily this and this.

My specific question is: How do I communicate Model changes from the Model to the ViewModel?<

11条回答
  •  感情败类
    2020-11-27 10:04

    If you want your Models to alert the ViewModels of changes, they should implement INotifyPropertyChanged, and the ViewModels should subscribe to receive PropertyChange notifications.

    Your code might look something like this:

    // Attach EventHandler
    PlayerModel.PropertyChanged += PlayerModel_PropertyChanged;
    
    ...
    
    // When property gets changed in the Model, raise the PropertyChanged 
    // event of the ViewModel copy of the property
    PlayerModel_PropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        if (e.PropertyName == "SomeProperty")
            RaisePropertyChanged("ViewModelCopyOfSomeProperty");
    }
    

    But typically this is only needed if more than one object will be making changes to the Model's data, which is not usually the case.

    If you ever have a case where you don't actually have a reference to your Model property to attach the PropertyChanged event to it, then you can use a Messaging system such as Prism's EventAggregator or MVVM Light's Messenger.

    I have a brief overview of messaging systems on my blog, however to summarize it, any object can broadcast a message, and any object can subscribe to listen for specific messages. So you might broadcast a PlayerScoreHasChangedMessage from one object, and another object can subscribe to listen for those types of messages and update it's PlayerScore property when it hears one.

    But I don't think this is needed for the system you have described.

    In an ideal MVVM world, your application is comprised of your ViewModels, and your Models are the just the blocks used to build your application. They typically only contain data, so would not have methods such as DrawCard() (that would be in a ViewModel)

    So you would probably have plain Model data objects like these:

    class CardModel
    {
        int Score;
        SuitEnum Suit;
        CardEnum CardValue;
    }
    
    class PlayerModel 
    {
        ObservableCollection FaceUpCards;
        ObservableCollection FaceDownCards;
        int CurrentScore;
    
        bool IsBust
        {
            get
            {
                return Score > 21;
            }
        }
    }
    

    and you'd have a ViewModel object like

    public class GameViewModel
    {
        ObservableCollection Deck;
        PlayerModel Dealer;
        PlayerModel Player;
    
        ICommand DrawCardCommand;
    
        void DrawCard(Player currentPlayer)
        {
            var nextCard = Deck.First();
            currentPlayer.FaceUpCards.Add(nextCard);
    
            if (currentPlayer.IsBust)
                // Process next player turn
    
            Deck.Remove(nextCard);
        }
    }
    

    (Above objects should all implement INotifyPropertyChanged, but I left it out for simplicity)

提交回复
热议问题