Hello World
Spiga

HTML Metro开发里的数据绑定(1):WinJS.Binding.List

2012-05-01 22:53 by 老赵, 2416 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的强大提示功能,可以让我们了解到该类型有哪些成员,例如:

WinJS.Binding.List事件

这样我们便能知道如何实现一些常见的场景:

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对应的元素,因此这个功能在某些情况下会很有帮助。

更有特色的可能是createFilteredcreateGroupedcreateSorted方法,他们都是在原有集合的基础上,返回一个(或一组)新的WinJS.Binding.List对象,每个新集合都和原有集合的内容保持“一致”。例如,基于一个过滤条件由createFiltered方法创建出来的新集合,假如向原集合添加一个满足该过滤条件的元素,则这个元素也会添加到新的容器里,同时触发新容器的iteminserted事件。同样,其他对原集合的修改也会影响新的集合。要实现类似的功能并不困难,只不过比较麻烦,如果您有兴趣,也不妨实验下。

相关文章

  • HTML Metro开发里的数据绑定(1):WinJS.Binding.List
Creative Commons License

本文基于署名 2.5 中国大陆许可协议发布,欢迎转载,演绎或用于商业目的,但是必须保留本文的署名赵劼(包含链接),具体操作方式可参考此处。如您有任何疑问或者授权方面的协商,请给我留言

Add your comment

2 条回复

  1. mathgl
    42.2.24.*
    链接

    mathgl 2012-05-02 19:50:38

    用上vs 11了??

  2. bigheadguo
    207.46.55.*
    链接

    bigheadguo 2012-05-03 10:16:19

    最近刚学 MVVM, 真的很强大

发表回复

登录 / 登录并记住我 ,登陆后便可删除或修改已发表的评论 (请注意保留评论内容)

昵称:(必填)

邮箱:(必填,仅用于Gavatar

主页:(可选)

评论内容(大于5个字符):

  1. Your Name yyyy-MM-dd HH:mm:ss

使用Live Messenger联系我