HTML Metro开发里的数据绑定(1):WinJS.Binding.List
2012-05-01 22:53 by 老赵, 3652 visits前段时间接触了一些WPF开发方面内容,了解如何使用MVVM模式将界面与模型几乎彻底分离开来,只通过其强大的绑定功能连接两者,让人叹为观止。Win8的Metro开发支持使用XAML(配合C#,C++等语言)或是HTML(配合JavaScript),前者的控件和数据的绑定已经相当完备,而后者一直没有一个标准的模型。之前我也简单了解过如Knockout这样的绑定支持与MVVM模式实现,理论上说也完全可以在Metro开发里使用,但其实Metro开发本身也已经提供了一些内置的绑定支持,基本对应于XAML/C#开发里涉及到的ObservableCollection与INotifyPropertyChanged。
ObservableCollection的功能是作为元素的集合,绑定到一个控件上去,当集合发生改变时,将会触发一个CollectionChanged事件,通知控件(或其他监听者)发生了什么样的变化:
public class ObservableCollection<T> { public event NotifyCollectionChangedEventHandler CollectionChanged; } public delegate void NotifyCollectionChangedEventHandler(object sender, NotifyCollectionChangedEventArgs e); public class NotifyCollectionChangedEventArgs : EventArgs { public NotifyCollectionChangedAction Action { get; } public IList NewItems { get; } public int NewStartingIndex { get; } public IList OldItems { get; } public int OldStartingIndex { get; } } public enum NotifyCollectionChangedAction { Add = 0, Remove = 1, Replace = 2, Move = 3, Reset = 4, }
ObservableCollection在Metro开发中的JavaScript对应物为WinJS.Binding.List类型,它包含许多成员,可惜目前文档奇缺,多亏Visual Studio 2011对JavaScript的强大提示功能,可以让我们了解到该类型有哪些成员,例如:
这样我们便能知道如何实现一些常见的场景:
var list = new WinJS.Binding.List(); list.push("Hello"); // iteminserted list.push("World"); // iteminserted list.push("How are you?"); // iteminserted list.setAt(0, "Hello World"); // itemchanged list.move(0, 2); // itemmoved list.slice(1, 2); // itemremoved list.notifyMutated(0); // itemmutated list.notifyReload(); // reload
与ObservableCollection的集中式CollectionChanged事件相比,WinJS.Binding.List的事件更为分散。此外,还有两个事件是需要外部方法notifyMutated和notifyReload来触发的。其中itemsMutated事件比较特殊,它似乎是在通知集合中某个元素自身状态产生了变化,在XAML开发中这事儿完全不关ObservableCollection管,而是后面要说的,由元素自己实现INotifyPropertyChanged接口来负责。
WinJS.Binding.List的各种接口和JavaScript数组基本一致,此外它还包括一些有趣的功能,例如它的构造函数可以传递一个数组以及一个options参数,如果options.proxy为true,则直接将该数组作为内部的存储结构。另外,其实这个集合会为其中每个元素分配一个key,通过getItem(index)可以得到一个key/value对,通过getItemFromKey可以通过key得到元素。交换数组中元素的顺序并不会改变key对应的元素,因此这个功能在某些情况下会很有帮助。
更有特色的可能是createFiltered,createGrouped和createSorted方法,他们都是在原有集合的基础上,返回一个(或一组)新的WinJS.Binding.List对象,每个新集合都和原有集合的内容保持“一致”。例如,基于一个过滤条件由createFiltered方法创建出来的新集合,假如向原集合添加一个满足该过滤条件的元素,则这个元素也会添加到新的容器里,同时触发新容器的iteminserted事件。同样,其他对原集合的修改也会影响新的集合。要实现类似的功能并不困难,只不过比较麻烦,如果您有兴趣,也不妨实验下。
相关文章
- HTML Metro开发里的数据绑定(1):WinJS.Binding.List
用上vs 11了??