如果模型未实现INotifyPropertyChanged,View Models如何从其底层模型传播更改通知?

时间:2021-11-14 07:11:44

Reading Josh Smiths article about MVVM his view model CustomerViewModel implements INotifyPropertyChanged but not the underlying Customer class.

阅读Josh Smiths关于MVVM的文章他的视图模型CustomerViewModel实现了INotifyPropertyChanged而不是底层的Customer类。

I can only see one (feasible) way to make change notification work in that case - only make changes to the CustomerViewModel and not the Customer. In that case, should the backend logic of my program also simply work against ViewModels? That seems pretty weird, they being View Models after all.

在这种情况下,我只能看到一种(可行的)方法来进行更改通知工作 - 只对CustomerViewModel而不是Customer进行更改。在这种情况下,我的程序的后端逻辑是否也只是针对ViewModels?这看起来很奇怪,毕竟他们是View Models。

Anyone that can clarify this a bit?

有人可以澄清这一点吗?

Thanks!

谢谢!

Clarification:

澄清:

Say that I've got a model Quote and a list of Quotes.

说我有一个模型报价和行情列表。

public class Quote
{
    public string Name { get; set; }
    public decimal Value { get; set; }
}

public QuoteViewModel : INotifyPropertyChanged
{
    private Quote quote;

    public event EventHandler PropertyChanged;

    public decimal Value 
    { 
         get { return quote.Value; }
         set
         { 
               quote.Value = value;
               PropertyChanged("Value");
         }
    }                  
}

Now, if Quote changes as a result of a background thread polling a web-service, the UI will not be notified of this, since Quote do not implement INotifyPropertyChanged, unless all parts of the system uses the ViewModel?

现在,如果由于后台线程轮询Web服务而引用更改,则不会通知UI,因为除非系统的所有部分都使用ViewModel,否则Quote不会实现INotifyPropertyChanged?

2 个解决方案

#1


2  

I'm guessing that in his example, he is using the notification to propagate changes to one part of the view to other parts of the view. Since the different portions are presumably bound to the same view-model, this would work.

我猜测在他的例子中,他正在使用通知将视图的一部分的更改传播到视图的其他部分。由于不同的部分可能被绑定到相同的视图模型,因此这将起作用。

Re logic validation; I probably wouldn't base that on change events anyway; firstly because that would be a lot of even subscriptions (contrast UI, where you only bind things the UI cares about), and secondly it is probably too important to risk missing ;p If the model isn't performing validation internally (as changes happen) then I would just run the validation logic explicitly before commit, looking at the members altogether. This also avoids the "briefly inconsistent" issue, i.e. where you plan to make several changes that result in a valid model, but if you validate immediately it is either really awkward to find a sequence that allows you to make the change you want, or is totally impossible. By deferring the validation, this goes away.

重新逻辑验证;无论如何,我可能不会以改变事件为基础;首先是因为这将是很多甚至订阅(对比UI,你只关注UI关心的东西),其次它可能太重要,不能冒险丢失; p如果模型没有在内部执行验证(因为变化发生)然后我会在提交之前显式运行验证逻辑,完全查看成员。这也避免了“短暂不一致”的问题,即您计划进行多次更改以产生有效模型,但如果您立即验证,找到允许您进行所需更改的序列真的很尴尬,或者完全不可能。通过推迟验证,这就消失了。

#2


0  

Marc makes some excellent points, but it sounds like you really need to modify the model outside of the context of your UI. Consider implementing INotifyPropertyChanged on your model, but as Marc mentioned, this will likely be a little problematic and certainly require significant testing. This approach would work best if your model is a POCO. If it can double as a psuedo-VM exposed in all the VMs that use it, then maybe you can minimize or eliminate VM->model event subscription:

Marc提出了一些很好的观点,但听起来你真的需要在UI的上下文之外修改模型。考虑在你的模型上实现INotifyPropertyChanged,但正如Marc所说,这可能会有点问题,当然需要进行大量的测试。如果您的模型是POCO,这种方法最有效。如果它可以兼作在所有使用它的VM中暴露的伪造的VM,那么也许你可以最小化或消除VM->模型事件订阅:

public QuoteViewModel : INotifyPropertyChanged
{
  private Quote quote;
  public event EventHandler PropertyChanged;
  public INotifyPropertyChanged Quote
  {
    get { return quote; }
    set
    {
      quote = value;
      PropertyChanged("Quote");
    }
  }
}

#1


2  

I'm guessing that in his example, he is using the notification to propagate changes to one part of the view to other parts of the view. Since the different portions are presumably bound to the same view-model, this would work.

我猜测在他的例子中,他正在使用通知将视图的一部分的更改传播到视图的其他部分。由于不同的部分可能被绑定到相同的视图模型,因此这将起作用。

Re logic validation; I probably wouldn't base that on change events anyway; firstly because that would be a lot of even subscriptions (contrast UI, where you only bind things the UI cares about), and secondly it is probably too important to risk missing ;p If the model isn't performing validation internally (as changes happen) then I would just run the validation logic explicitly before commit, looking at the members altogether. This also avoids the "briefly inconsistent" issue, i.e. where you plan to make several changes that result in a valid model, but if you validate immediately it is either really awkward to find a sequence that allows you to make the change you want, or is totally impossible. By deferring the validation, this goes away.

重新逻辑验证;无论如何,我可能不会以改变事件为基础;首先是因为这将是很多甚至订阅(对比UI,你只关注UI关心的东西),其次它可能太重要,不能冒险丢失; p如果模型没有在内部执行验证(因为变化发生)然后我会在提交之前显式运行验证逻辑,完全查看成员。这也避免了“短暂不一致”的问题,即您计划进行多次更改以产生有效模型,但如果您立即验证,找到允许您进行所需更改的序列真的很尴尬,或者完全不可能。通过推迟验证,这就消失了。

#2


0  

Marc makes some excellent points, but it sounds like you really need to modify the model outside of the context of your UI. Consider implementing INotifyPropertyChanged on your model, but as Marc mentioned, this will likely be a little problematic and certainly require significant testing. This approach would work best if your model is a POCO. If it can double as a psuedo-VM exposed in all the VMs that use it, then maybe you can minimize or eliminate VM->model event subscription:

Marc提出了一些很好的观点,但听起来你真的需要在UI的上下文之外修改模型。考虑在你的模型上实现INotifyPropertyChanged,但正如Marc所说,这可能会有点问题,当然需要进行大量的测试。如果您的模型是POCO,这种方法最有效。如果它可以兼作在所有使用它的VM中暴露的伪造的VM,那么也许你可以最小化或消除VM->模型事件订阅:

public QuoteViewModel : INotifyPropertyChanged
{
  private Quote quote;
  public event EventHandler PropertyChanged;
  public INotifyPropertyChanged Quote
  {
    get { return quote; }
    set
    {
      quote = value;
      PropertyChanged("Quote");
    }
  }
}