CollectionView Notifications and Performance

The CollectionView class is highly optimized. It sorts, filters, groups, and paginates large data sets efficiently in virtually every situation.

In some cases, you may be able to improve performance even more by using the deferUpdate method to suspend refreshes while performing batch operations.

This is especially important when adding items to collections that are sorted, grouped, or filtered. Without deferred updates, each addition causes a refresh.

For example, click the buttons below to add 1,000 items to a CollectionView using three different methods:



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
// This file locates: "Scripts/Lesson/C1Mvc/CVPerformance.js".
c1.documentReady(function () {
    // create some random data
    // Note that we are using an ObservableArray rather than a regular
    // JavaScript array. The ObservableArray raises events when items
    // are added or removed.
    // If we used a regular array, we would have to call the
    // CollectionView.refresh() method to update the view after
    // adding or removing items.
    var countries = 'US,Germany,UK,Japan,Italy,Greece'.split(',');
    var data = new wijmo.collections.ObservableArray();
 
    function getItem(i) {
        return {
            country: countries[i % countries.length],
            downloads: Math.round(Math.random() * 20000),
            sales: Math.random() * 10000,
            expenses: Math.random() * 5000,
            active: i % 4 == 0
        }
    }
 
    // create a CollectionView
    var view = new wijmo.collections.CollectionView(data, {
        sortDescriptions: ['country'],
        newItemCreator: function () {
            return getItem(view.sourceCollection.length);
        }
    });
 
    // add items with addNew
    document.getElementById('btnAddNew').addEventListener('click', function (e) {
        var start = Date.now();
        view.sourceCollection.clear();
        for (var i = 0; i < 1000; i++) {
            view.addNew();
            view.commitNew();
        }
        alert('addNew done in ' + (Date.now() - start) + 'ms');
    });
 
    // add items with push
    document.getElementById('btnPush').addEventListener('click', function (e) {
        var start = Date.now();
        view.sourceCollection.clear();
        for (var i = 0; i < 1000; i++) {
            view.sourceCollection.push(getItem(i));
        }
        alert('push done in ' + (Date.now() - start) + 'ms');
    });
 
    // add items with pushDefer
    document.getElementById('btnPushDefer').addEventListener('click', function (e) {
        var start = Date.now();
        view.sourceCollection.clear();
        view.deferUpdate(function () {
            for (var i = 0; i < 1000; i++) {
                view.sourceCollection.push(getItem(i));
            }
        })
        alert('pushDefer done in ' + (Date.now() - start) + 'ms');
    });
});
1
2
3
4
5
6
7
8
9
10
11
12
13
using System.Web.Mvc;
 
namespace LearnMvcClient.Controllers
{
    public partial class C1MvcController : Controller
    {
        // GET: CVPerformance
        public ActionResult CVPerformance()
        {
            return View();
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<h1>
    @Html.Raw(Resources.C1Mvc.CVPerformance_Title)
</h1>
<p>
    @Html.Raw(Resources.C1Mvc.CVPerformance_Text1)
</p>
<p>
    @Html.Raw(Resources.C1Mvc.CVPerformance_Text2)
</p>
<p>
    @Html.Raw(Resources.C1Mvc.CVPerformance_Text3)
</p>
<p>
    @Html.Raw(Resources.C1Mvc.CVPerformance_Text4)
</p>
 
<button id="btnAddNew" class="btn btn-default">
    @Html.Raw(Resources.C1Mvc.CVPerformance_Text5)
</button>
<br>
<button id="btnPush" class="btn btn-default">
    @Html.Raw(Resources.C1Mvc.CVPerformance_Text6)
</button>
<br>
<button id="btnPushDefer" class="btn btn-default">
    @Html.Raw(Resources.C1Mvc.CVPerformance_Text7)
</button>