WPF 中的 MVVM - 如何提醒 ViewModel 模型中的变化......还是我应该? [英] MVVM in WPF - How to alert ViewModel of changes in Model... or should I?

查看:43
本文介绍了WPF 中的 MVVM - 如何提醒 ViewModel 模型中的变化......还是我应该?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在阅读一些 MVVM 文章,主要是this这个.

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

我的具体问题是:如何将 Model 更改从 Model 传达到 ViewModel?

在 Josh 的文章中,我没有看到他这样做.ViewModel 总是向 Model 询问属性.在 Rachel 的示例中,她确实让模型实现了 INotifyPropertyChanged,并从模型中引发事件,但它们供视图本身使用(有关她为什么这样做的更多详细信息,请参阅她的文章/代码).

In Josh's article, I don't see that he does this. The ViewModel always asks the Model for properties. In Rachel's example, she does have the model implement INotifyPropertyChanged, and raises events from the model, but they are for consumption by the view itself (see her article/code for more detail on why she does this).

我在任何地方都没有看到模型提醒 ViewModel 模型属性更改的示例.这让我担心可能由于某种原因没有完成.是否有一种模式可以提醒 ViewModel 模型中的变化? 这似乎是必要的,因为 (1) 可以想象每个模型有 1 个以上的 ViewModel,并且 (2) 即使有只有一个 ViewModel,对模型的某些操作可能会导致其他属性发生更改.

Nowhere do I see examples where the model alerts the ViewModel of changes to model properties. This has me worried that perhaps it's not done for some reason. Is there a pattern for alerting the ViewModel of changes in the Model? It would seem to be necessary as (1) conceivably there are more than 1 ViewModel for each model, and (2) even if there is just one ViewModel, some action on the model might result in other properties being changed.

我怀疑可能会有您为什么要这样做?"形式的答案/评论.评论,所以这里是我的程序的描述.我是 MVVM 的新手,所以也许我的整个设计有问题.我将简要描述一下.

I suspect that there might be answers/comments of the form "Why would you want to do that?" comments, so here's a description of my program. I'm new to MVVM so perhaps my whole design is faulty. I'll briefly describe it.

我正在编写比客户"或产品"类更有趣(至少对我而言!)的东西.我正在编程二十一点.

I am programming up something that is more interesting (at least, to me!) than "Customer" or "Product" classes. I am programming BlackJack.

我有一个没有任何代码的视图,它只依赖于绑定到 ViewModel 中的属性和命令(请参阅 Josh Smith 的文章).

I have a View that doesn't have any code behind and just relies on binding to properties and commands in the ViewModel (see Josh Smith's article).

无论好坏,我认为模型不仅应该包含PlayingCardDeck等类,还应该包含BlackJackGame 保持整个游戏状态的类,并知道玩家何时破产,庄家必须抽牌,以及玩家和庄家当前分数是多少(小于 21、21、破产等).

For better or worse, I took the attitude that the Model should contain not just classes such as PlayingCard, Deck, but also the BlackJackGame class that keeps state of the whole game, and knows when the player has gone bust, the dealer has to draw cards, and what the player and dealer current score is (less than 21, 21, bust, etc.).

BlackJackGame 中,我公开了DrawCard"之类的方法,我突然想到,在抽取卡片时,诸如 CardScoreIsBust 应该更新,并将这些新值传达给 ViewModel.也许这是错误的想法?

From BlackJackGame I expose methods like "DrawCard" and it occurred to me that when a card is drawn, properties such as CardScore, and IsBust should be updated and these new values communicated to the ViewModel. Perhaps that's faulty thinking?

人们可以认为 ViewModel 调用了 DrawCard() 方法,因此他应该知道要求更新分数并确定他是否破产.意见?

One could take the attitude that the ViewModel called the DrawCard() method so he should know to ask for an updated score and find out if he is bust or not. Opinions?

在我的 ViewModel 中,我有逻辑来抓取一张扑克牌的实际图像(基于花色、等级)并使其可用于视图.模型不应该关心这个(也许其他 ViewModel 只会使用数字而不是扑克牌图像).当然,也许有人会告诉我,Model 甚至不应该有 21 点游戏的概念,而应该在 ViewModel 中处理?

In my ViewModel, I have the logic to grab an actual image of a playing card (based on suit,rank) and make it available for the view. The model should not be concerned with this (perhaps other ViewModel would just use numbers instead of playing card images). Of course, perhaps some will tell me that the Model should not even have the concept of a BlackJack game and that should be handled in the ViewModel?

推荐答案

如果您希望您的模型向 ViewModels 发出更改警报,它们应该实施 INotifyPropertyChanged,并且 ViewModel 应订阅以接收 PropertyChange 通知.

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.

如果您遇到过实际上没有引用 Model 属性来将 PropertyChanged 事件附加到它的情况,那么您可以使用消息系统,例如 Prism 的 EventAggregator 或 MVVMLight的信使.

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.

我有一个消息系统的简要概述博客,但是总结一下,任何对象都可以广播消息,任何对象都可以订阅以收听特定消息.因此,您可以从一个对象广播 PlayerScoreHasChangedMessage,另一个对象可以订阅以侦听这些类型的消息,并在听到消息时更新它的 PlayerScore 属性.

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.

在理想的 MVVM 世界中,您的应用程序由您的 ViewModel 组成,而您的模型只是用于构建您的应用程序的块.它们通常只包含数据,因此不会有诸如 DrawCard() 之类的方法(在 ViewModel 中)

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<Card> FaceUpCards;
    ObservableCollection<Card> FaceDownCards;
    int CurrentScore;

    bool IsBust
    {
        get
        {
            return Score > 21;
        }
    }
}

你会有一个像

public class GameViewModel
{
    ObservableCollection<CardModel> 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);
    }
}

(以上对象都应该实现INotifyPropertyChanged,但为了简单起见我省略了)

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

这篇关于WPF 中的 MVVM - 如何提醒 ViewModel 模型中的变化......还是我应该?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆