January 21, 2014

Using custom binding to manage large datasets with the Kendo Grid

The KendoUI grid comes with robust client-side functionality, and Ajax-capabilities - sorting, filtering, paging is all just built in. With the Razor wrapper, the .Pageable(), .Sortable(), and .Filterable() extension methods take care of it all. If the data you’re displaying is minimal or even a few thousand rows, this is probably the route to go – just set the grid's dataSource to Ajax, create a read action on your controller, and you’ve got a pretty robust grid.

But once you get into dealing with “large” datasets, you may want to consider implementing custom binding to get data in front of the user without the wait. When I say “large”, I mean data that takes more than a few seconds to display, or data that is likely grow quickly to an unmanageable size. In our scenario the size of the dataset could be up to 25 Mb, but even after compressing it to 800k, it was taking several seconds to send the data from the server to the browser and then display the data in the grid. After the painful initial wait though, paging, sorting, filtering was then instantaneous since the data was all client side. But what to do about the initial wait?

That’s where custom binding can help out. By implementing custom binding, you can combine the best of Ajax and Server binding to quickly deliver large datasets to your users. A small drawback is that all the sorting, filtering, paging has to be handled in the controller method. Fortunately Kendo makes this fairly easy by automatically passing collections of criteria on the request object – here’s a quick overview of server code required to manually implement paging, sorting and filtering when implementing custom binding.

Sorting
The sorts collection on the request object contains the fields and directions of all sorts that are currently applied to the grid.

Filtering
This is beautiful – I was expecting to have to write code to handle all possible operators and fields, but Kendo’s ExpressionBuilder class will take the filters collection from the request and convert it to a lambda expression to be applied to your dataset! Way easy.

Paging
Based on the page number and the page size, determine the subset of data to return to the client.

One other thing to remember when implementing custom binding is that Server caching of the dataset is something to keep in mind – especially if the db call takes more than a second or two. With custom binding, we’re calling back to the server on every filter, page, or sort event – so we don’t want to make a db call on top of that every time. This is true even (and especially) if we use Kendo’s Server databinding instead of Ajax databinding. So anyway, if you’re using Kendo’s data grids, the out of the box Ajax binding is a good, easily implementable solution, but if you’re dealing with large amounts of data, you’ll want to look into custom binding.

Full Razor code for grid with custom binding enabled:



Full controller method for grid Read event:

Share |

August 02, 2013

Manipulating Kendo's RangeSlider via JavaScript

After dealing with Kendo's Range Slider control this afternoon, I thought it would be worthwhile to post some sample code for dealing with this control on the client side. Manipulating the RangeSlider on the client side is very simple and straightforward, but there isn't good documentation of this control, which has many properties and methods, so you could wind up spending a lot of time grasping at straws.

Kendo's RangeSlider control:

We're creating this control in an ASP.Net MVC project using Razor syntax:
@(Html.Kendo().RangeSlider()

    .Name("RangeSlider")

    .Max((double)Model.RevenueUpperBound)

    .Min((double)Model.RevenueLowerBound)

    .Values(Model.MinVal, Model.MaxVal)

    .Events(events => events.Change(x => "updateVals")))

But after the page is rendered, we want to programmatically change the start and end points via JavaScript. Looking at the object in FireBug, you can see several promising properties and methods like selectionStart, selectionEnd, bind(), etc... But ultimately, you'll just want to new up a JavaScript array containing the two integer values you want to use as the start and end values.

The example below resets our RangeSlider to a start value of 10 and an end value of 111. (Make sure your start and end values are between the upper and lower boundaries of the control itself).
function resetSlider(){

  //Get a handle on our element's RangeSlider
  var slider = $('#RangeSlider').data('kendoRangeSlider')

  //Feed it an array of two numbers.
  slider.value(new Array(10, 111))

}
That's it... As easy as 3.14.

Share |

April 17, 2013

Multitudes / Animal Collective names


Correct multitude naming per animal, in case you were wondering. Back to software-related info next post :)

A Crash of Rhinoceroses. 
A School of Fish. 
A Litter of Pups. 
A Flock of Sheep. 
A String of Ponies. 
A Harras of Horses.
A Pride of Lions.
A Herd of  Elephants. 
A Plague of Locusts. 
A Colony of Ants. 
A Covey of Quail.
A Kindle of Kittens. 
A Leap of Leopards.
A Pod of Seals. 
A Sloth of Bears. 
A Rafter of Turkeys. 
A Pace of Asses.
A Walk of Snipe.
A Gam of Whales. 
A Nest of Rabbits. 
A Gang of Elk. 
A Quiver of Cobra. 
A Dule of Doves.  
A Skulk of Foxes. 
A Dissimulation of Birds. 
A Prickle of Porcupines. 
A Peep of Chickens. 
A Band of Gorillas.
A Business of Ferrets.
A Bale of Turtles. 
A Pitying of Turtledoves. 
A Drift of Hogs. 
A Paddling of Ducks. 
A Siege of Herons. 
A Trip of Goats. 
A Charm of Finches. 
A Cete of Badgers. 
A Squadron of Pelicans. 
A Shoal of Bass. 
An Exaltation of Larks.
A Drove of Cattle. 
A Singular of Boars. 
A Tidings of Magpies. 
A Gaggle of Geese.
A Flutter of Butterflies. 
A Husk of Hares. 
An Unkindness of Ravens. 
A Labor of Moles. 
A Richness of Martens. 
A Cast of Hawks. 
A Knot of Toads. 
A Descent of Woodpeckers. 
A Sounder of Swine. 
A Mustering of Storks.
A Clutch of Eggs. 
A Bouquet of Pheasants.
An Army of Caterpillars. 
A Hover of Trout. 
A Flight of Swallows. 
A Troop of Kangaroos. 
A Clowder of Cats. 
A Watch of Nightingales. 
A Barren of Mules. 
A Shrewdness of Apes.
A Rag of Colts. 
A Bloat of Hippos.  
A Smack of Jellyfish. 
A Mischief of Mice. 
A Congregation of Alligators.  
A Parliament of Owls. 
A Route of Wolves. 
A Host of Sparrows. 
An Ostentation of Peacocks.
A Murder of Crows.

Share |

November 20, 2012

Hats off to CodeProject, Intel

CodeProject is currently holding a Windows 8 & Ultrabook App Innovation contest and I was fortunate enough to make it to the second round. It's a great contest, as all first round winners, myself included, were winners of a brand spanking new prototype model Ultrabook for development:
4Gb memory, Intel I-7(Ivy Bridge) Processor 2-2.5GHz,
160Gb HD, 5 Touchpoint Screen, Windows 8 OS.


I don't really have any technical points in this post, but I wanted to give some kudos to the folks at CodeProject as well as Intel, since I did have an issue with my screen cracking after a week or two. Since it was a free laptop, and CodeProject barely knows who I am, I was not hopeful about being able to get this issue resolved. And it's an unbranded prototype, so I wasn't really sure what manufacturer would be able to help me. Plus, it's a touch screen, so you can't just replace the glass like other laptops (even though it was still fully functional using mouse and keyboard).

But Chris at CodeProject pointed me to Premier Intel support, which came with the laptop, and they swapped it out for me as soon as I could give them a UPS tracking number. Five days later, I'm up and running on the replacement, and it's the best laptop I've ever owned. Fast, responsive, and boots to a functional Windows 8 login screen within 5 seconds. Thanks, CodeProject!

Share |

November 13, 2012

Windows 8 Store Deployment - Lessons Learned

After finally getting an app deployed to the Windows 8 Store, I wanted to share some learning experiences. I went through 2 multiple-hour sessions with the MS engineers - the first session focused more on coding and performance and uncovered the fact that the app was consuming a great deal of memory. It ended up that a few simple jQuery animations - which functioned OK in all other browsers including IE9  - went through the roof on memory consumption in IE10. So I minimized the jQuery animations and it resolved that issue, and now I am looking into revisiting it with the current version of IE10 and the RTM version of Windows 8.

The second interview dealt more with Win8/Metro standards and things like using Settings and the positioning of elements on the screen. At that point I was ready to deploy to the web store, which is a time-consuming process. I did find that having concise notes pertinent to each deployment did help speed up the turnaround time - the first submission took about 5 days to be rejected. By the time it was finally approved, I had deployed 3 times in one day, entering very specific details of the changes I was submitting.

A few things that bit me especially hard:
Certification Requirement #4.1 - Privacy Statement. If you use ANY user information, which includes accessing geolocation, you have to mention this in the privacy statement.

Also, if you have a privacy statement you must include it in your settings, AS WELL AS a link to a privacy statement HTML page in your store description.

Certification Requirement #6.2 - Age Rating. You have a clean app, right? Clean content, and you just implement the Sharing source contract so people can share text or an image from your app to Twitter, Facebook or whatever social network. Well, you'll have to make sure your age rating is 12+ for "uncontrolled sharing", or else you'll surely be rejected.

If you want to "control" sharing, you'll have to create some custom code to enable the user to "allow" other users to share from your application. So, assuming you're not targeting the 3 to 11-year-old crowd, you'll want to set your app's age rating to 12+ any time you implement the Sharing Source contract.

Share |