ViewModels和数据绑定
在MVVM的许多相当简单的演示中,模型不存在或仅暗示,并且ViewModel包含所有业务逻辑。 View和ViewModel通过基于XAML的数据绑定进行通信。 视图中的可视元素是数据绑定目标,ViewModel中的属性是数据绑定源。
理想情况下,ViewModel应独立于任何特定平台。 除了Xamarin.Forms之外,这种独立性允许ViewModel在其他基于XAML的环境(例如Windows)之间共享。 因此,您应该尽量避免在ViewModel中使用以下语句:
using Xamarin.Forms;
本章经常打破这条规则! 其中一个ViewModel基于Xamarin.Forms Color结构,另一个使用Device.StartTimer。 因此,让我们在ViewModel中调用避免Xamarin.Forms特有的任何“建议”而不是“规则”。
View中的可视元素有资格作为数据绑定目标,因为这些可视元素的属性由可绑定属性支持。 要成为数据绑定源,ViewModel必须实现通知协议,以便在ViewModel中的属性发生更改时发出信号。 此通知协议是INotifyPropertyChanged接口,它仅在一个事件中非常简单地在System.ComponentModel命名空间中定义:
public interface INotifyPropertyChanged
{
event PropertyChangedEventHandler PropertyChanged;
}
NotifyPropertyChanged接口是MVVM的核心,在非正式讨论中,接口通常缩写为INPC。
INotifyPropertyChanged接口中的PropertyChanged事件的类型为PropertyChanged-EventHandler。 此PropertyChanged事件处理程序的处理程序获取PropertyChangedEventArgs类的实例,该类定义名为PropertyName的类型为string的单个属性,指示ViewModel中的哪个属性已更改。 然后,事件处理程序可以访问该属性。
实现INotifyPropertyChanged的类应该在公共属性发生更改时触发PropertyChanged事件,但是在仅设置属性但未更改属性时,类不应触发事件。
有些类定义了不可变属性 - 在构造函数中初始化的属性,然后永远不会更改。 这些属性不需要触发PropertyChanged事件,因为只有在构造函数中的代码完成后才能附加PropertyChanged处理程序,并且不可变属性在此之后永远不会更改。
理论上,ViewModel类可以从BindableObject派生,并将其公共属性实现为BindableProperty对象。 BindableObject实现INotifyPropertyChanged,并在BindableProperty支持的任何属性发生更改时自动触发PropertyChanged事件。 但是从BindableObject派生对于ViewModel来说是过度的。 因为BindableObject和BindableProperty特定于Xamarin.Forms,所以这样的ViewModel不再是平台无关的,并且该技术与简单的INotifyPropertyChanged实现相比没有真正的优势。