On Demand Data Loading in XamGrid and XamDataTree

 

Loading data on demand is typical of applications that use hierarchical data. The article “On Demand Data Loading in XamTree” demonstrated an application using Infragistics XamTree. This article shows how they could benefit from hierarchical data XamGrid and XamDataTree as load only the data that is necessary to show.

Requirements:

  1. NetAdvantage for Silverlight  Line of Business 2010 Vol.3
  2. NetAdvantage for .NET 2010 Vol.3
  3. NetAdvantage Ultimate 2010 Vol.3

 

Sample data:

Demo application uses a sample data from XML file.
Sample application uses the same like the data from the article “On Demand Data Loading in XamTree” 

   1: <?xml version="1.0" encoding="utf-8" ?>

   2: <books>

   3:   <book Title="The Elegant Universe" Author="Brian Greene" UnitPrice="15.95" Url="http://www.amazon.com/Elegant-Universe-Superstrings-Dimensions-Ultimate/dp/0393046885" ReleaseDate="02/01/1999" >

   4:     <chapter Title="Tied Up with String" />

   5:     <chapter Title="Space, Time, and the Eye of the Beholder" />

   6:     <chapter Title="Of Warps and Ripples" />

   7:     <chapter Title="Microscopic Weirdness" />

   8:     <chapter Title="The Need for a New Theory: General Relativity vs. Quantum Mechanics" />

   9:     <chapter Title="Nothing but Music: The Essentials of Superstring Theory" />

  10:     <chapter Title="The &quot;Super&quot; in Superstrings" />

  11:     <chapter Title="More Dimensions Than Meet the Eye" />

  12:     <chapter Title="The Smoking Gun: Experimental Signatures" />

  13:     <chapter Title="Quantum Gravity" />

  14:     <chapter Title="Tearing the Fabric of Space" />

  15:     <chapter Title="Beyond Strings: In Search of M-Theory" />

  16:     <chapter Title="Black Holes: A String/M-Theory Perspective" />

  17:     <chapter Title="Reflections on Cosmology" />

  18:     <chapter Title="Prospects" />

  19:   </book>

  20:  

  21:   <book Title="Dive Into Python" Author="Mark Pilgrim" UnitPrice="39.99" Url="http://www.amazon.com/Dive-Into-Python-Mark-Pilgrim/dp/1590593561" ReleaseDate="07/19/2004" >

  22:     <chapter Title="Installing Python" />

  23:     <chapter Title="Your First Python Program" />

  24:     <chapter Title="Native Datatypes" />

  25:     <chapter Title="The Power of Introspection" />

  26:     <chapter Title="Objects and Object-Orientation" />

  27:     <chapter Title="Exceptions and File Handling" />

  28:     <chapter Title="Regular Expressions" />

  29:     <chapter Title="HTML Processing" />

  30:     <chapter Title="XML Processing" />

  31:     <chapter Title="Scripts and Streams" />

  32:     <chapter Title="HTTP Web Services" />

  33:     <chapter Title="SOAP Web Services" />

  34:     <chapter Title="Unit Testing" />

  35:     <chapter Title="Test-First Programming" />

  36:     <chapter Title="Refactoring" />

  37:     <chapter Title="Functional Programming" />

  38:     <chapter Title="Dynamic Functions" />

  39:     <chapter Title="Performance Tuning" />

  40:   </book>

  41:  

  42:   <book Title="The Selfish Gene (30th Anniversary Edition)" Author="Richard Dawkins" UnitPrice="15.95" Url="http://www.amazon.com/Selfish-Gene-Anniversary-Introduction/dp/0199291152" ReleaseDate="05/25/2006" >

  43:     <chapter Title="Why are people?" />

  44:     <chapter Title="The replicators" />

  45:     <chapter Title="Immortal coils" />

  46:     <chapter Title="The gene machine" />

  47:     <chapter Title="Aggression: stability and the selfish machine" />

  48:     <chapter Title="Genesmanship" />

  49:     <chapter Title="Family planning" />

  50:     <chapter Title="Battle of the generations" />

  51:     <chapter Title="Battle of the sexes" />

  52:     <chapter Title="You scratch my back, I'll ride on yours" />

  53:     <chapter Title="Memes: the new replicators" />

  54:     <chapter Title="Nice guys finish first" />

  55:     <chapter Title="The long reach of the gene" />

  56:   </book>

  57:  

  58:   <book Title="The Ideological Origins of the American Revolution (Enlarged Edition)" Author="Bernard Bailyn" UnitPrice="24.00" Url="http://www.amazon.com/Ideological-Origins-American-Revolution/dp/0674443020" ReleaseDate="03/01/1992" >

  59:     <chapter Title="The Literature of Revolution" />

  60:     <chapter Title="Sources and Traditions" />

  61:     <chapter Title="Power and Liberty: A Theory of Politics" />

  62:     <chapter Title="The Logic of Rebellion" />

  63:     <chapter Title="Transformation" />

  64:     <chapter Title="The Contagions of Liberty" />

  65:     <chapter Title="Fulfillment: A Commentary on the Constitution" />

  66:   </book>

  67:  

  68:   <book Title="Gödel, Escher, Bach: an Eternal Golden Braid" Author="Douglas R. Hofstadter" UnitPrice="20.00" Url="http://www.amazon.com/Godel-Escher-Bach-Douglas-Hofstadter/dp/B001IAM392" ReleaseDate="01/01/1999" >

  69:     <chapter Title="The MU-puzzle." />

  70:     <chapter Title="Meaning and Form in Mathematics." />

  71:     <chapter Title="Figure and Ground." />

  72:     <chapter Title="Consistency, Completeness, and Geometry." />

  73:     <chapter Title="Recursive Structures and Processes." />

  74:     <chapter Title="The Location of Meaning." />

  75:     <chapter Title="The Propositional Calculus." />

  76:     <chapter Title="Typographical Number Theory." />

  77:     <chapter Title="Mumon and Gödel." />

  78:     <chapter Title="Levels of Description, and Computer Systems." />

  79:     <chapter Title="Brains and Thoughts." />

  80:     <chapter Title="Minds and Thoughts." />

  81:     <chapter Title="BlooP and FlooP and GlooP." />

  82:     <chapter Title="On Formally Undecidable Propositions of TNT and Related Systems." />

  83:     <chapter Title="Jumping out of the System." />

  84:     <chapter Title="Self-Ref and Self-Rep." />

  85:     <chapter Title="Church, Turing, Tarski, and Others." />

  86:     <chapter Title="Artificial Intelligence: Retrospects." />

  87:     <chapter Title="Artificial Intelligence: Prospects." />

  88:     <chapter Title="Strange Loops, Or Tangled Hierarchies." />

  89:   </book>

  90:  

  91:   <book Title="Silverlight 1.0" Author="Devin Rader, Jason Beres, J. Ambrose Little, Grant Hinkson" UnitPrice="23.37" Url="http://www.amazon.com/Silverlight-1-0-Devin-Rader/dp/0470228407" ReleaseDate="10/29/2007" >

  92:    <chapter Title="Introduction to Silverlight" />

  93:     <chapter Title="Building Silverlight Applications Using XAML" />

  94:     <chapter Title="Designing Silverlight Applications Using Expression Blend 2"  />

  95:     <chapter Title="Coding Silverlight Applications with JavaScript and XAML"  />

  96:     <chapter Title="Using Silverlight with ASP.NET"  />

  97:     <chapter Title="Silverlight 1.1 and the CLR"  />

  98:     <chapter Title="Video Player: Silverlight 1.0 Case Example"  />

  99:   </book>

 100:   <book Title="Harry Potter and the Deathly Hallows" Author="J. K. Rowling" UnitPrice="20.99" Url="http://www.amazon.com/Harry-Potter-Deathly-Hallows-Book/dp/0545010225" ReleaseDate="07/21/2007" />

 101:   <book Title="Silverlight 2 Silverlight 2 Programmer's Reference's Reference" Author="J. Ambrose Little, Jason Beres, Grant Hinkson, Devin Rader, Joe Croney" UnitPrice="31.49" Url="http://www.amazon.com/Silverlight-Programmers-Reference-Ambrose-Little/dp/0470385405" ReleaseDate="03/23/2009" />

 102:   <book Title="Breaking Dawn (The Twilight Saga, Book 4)" Author="Stephenie Meyer" UnitPrice="12.64" Url="http://www.amazon.com/New-Moon-Twilight-Saga-Book/dp/0316024961" ReleaseDate="08/02/2008" />

 103:   <book Title="The Last Lecture" Author="Randy Pausch and Jeffrey Zaslow" UnitPrice="13.17" Url="http://www.amazon.com/Last-Lecture-Randy-Pausch/dp/1401323251" ReleaseDate="04/08/2008" />

 104:   <book Title="Brisingr" Author="Christopher Paolini" UnitPrice="16.50" Url="http://www.amzon.com/Brisingr-Inheritance-Book-Christopher-Paolini/dp/0375826726" ReleaseDate="09/20/2008" />

 105:   <book Title="The Story of Edgar Sawtelle" Author="David Wroblewski" UnitPrice="14.27" Url="http://www.amazon.com/Story-Edgar-Sawtelle-Novel-Oprah/dp/0061768065" ReleaseDate="09/19/2008"  />

 106:   <book Title="The Tales of Beedle the Bard" Author="J. K. Rowling" UnitPrice="7.14" Url="http://www.amazon.com/Tales-Beedle-Bard-Standard/dp/0545128285" ReleaseDate="12/04/2008" />

 107:   <book Title="The Appeal" Author="John Grisham " UnitPrice="18.45" Url="http://www.amazon.com/Appeal-John-Grisham/dp/0385515049" ReleaseDate="01/29/2008" />

 108:   <book Title="When You Are Engulfed in Flames" Author="David Sedaris" UnitPrice="15.59" Url="http://www.amazon.com/When-You-Are-Engulfed-Flames/dp/0316143472" ReleaseDate="06/03/2008" />

 109:   <book Title="In Defense of Food: An Eater's Manifesto" Author="Michael Pollan" UnitPrice="13.17" Url="http://www.amazon.com/Defense-Food-Eaters-Manifesto/dp/1594201455" ReleaseDate="01/01/2008" />

 110:   <book Title="The Revolution: A Manifesto" Author="Ron Paul" UnitPrice="13.17" Url="http://www.amazon.com/Host-Novel-Stephenie-Meyer/dp/031606804" ReleaseDate="04/01/2008" />

 111:   <book Title="The Host: A Novel" Author="Stephenie Meyer " UnitPrice="13.17" Url="http://www.amazon.com/Host-Novel-Stephenie-Meyer/dp/031606804" ReleaseDate="05/06/2008" />

 112:   <book Title="The Post-American World" Author="Fareed Zakaria" UnitPrice="17.13" Url="http://www.amazon.com/Post-American-World-Fareed-Zakaria/dp/039306235X" ReleaseDate="05/05/2008" />

 113:   <book Title="Hungry Girl" Author="Lisa Lillien" UnitPrice="12.21" Url="http://www.amazon.com/Hungry-Girl-Survival-Strategies-Guilt-Free/dp/0312377428" ReleaseDate="04/29/2008" />

 114:   <book Title="Fearless Fourteen (Stephanie Plum, No. 14)" Author="Janet Evanovich" UnitPrice="18.45" Url="http://www.amazon.com/Fearless-Fourteen-Stephanie-Plum-No/dp/0312349513" ReleaseDate="06/17/2008" />

 115:   <book Title="The Tales of Beedle the Bard, Collector's Edition" Author="J. K. Rowling" UnitPrice="100.00" Url="http://www.amazon.com/Beedle-Collectors-Offered-Exclusively-Amazon/dp/0956010903" ReleaseDate="12/04/2008" />

 116:   <book Title="Unaccustomed Earth" Author="Jhumpa Lahiri" UnitPrice="16.50" Url="http://www.amazon.com/Unaccustomed-Earth-Jhumpa-Lahiri/dp/0307265730" ReleaseDate="04/01/2008" />

 117:   <book Title="sTORI Telling" Author="Tori Spelling" UnitPrice="16.47" Url="http://www.amazon.com/sTORI-Telling-Tori-Spelling/dp/1416950737" ReleaseDate="03/11/2008" />

 118:   <book Title="Audition: A Memoir" Author="Barbara Walters" UnitPrice="19.77" Url="http://www.amazon.com/Audition-Memoir-Barbara-Walters/dp/030726646X"  ReleaseDate="05/06/2008" />

 119: </books>

 

Steps to reproduce:

  • Download sample data
  • Create a sample Silverlight Navigation Application, hosted in an ASP.Net application.
  • Imeplement a Silverlight-enabled WCF service that returns collections of book and book chapters.
  • Create in the Silverlight application a  MVVM using for data custom collections that inherits VirtualCollection<T>

WCF Service implementation:
WCF service implementation is almost the same like in the article:  “On Demand Data Loading in XamTree” 

Create a new Silverlight-enabled WCF service, named BookDataSourceService :

XamGridLazyLoading_Pic02

BookDataSourceService implementation:

   1: #region BookDataSourceService

   2: [ServiceContract(Namespace = "")]

   3: [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]

   4: public class BookDataSourceService

   5: {

   6:  

   7:     #region Member Variables

   8:  

   9:     static string dataPath = HttpContext.Current.Server.MapPath(".") + Path.DirectorySeparatorChar +

  10:    ConfigurationManager.AppSettings["DataDirectory"] + Path.DirectorySeparatorChar +

  11:                    ConfigurationManager.AppSettings["DataFile"];

  12:  

  13:     static XDocument doc = XDocument.Load(dataPath);

  14:  

  15:     #region GetBookCount

  16:     [OperationContract]

  17:     public int GetBookCount()

  18:     {

  19:         try

  20:         {

  21:             return doc.Descendants("book").Count();

  22:         }

  23:         catch (Exception)

  24:         {

  25:             return 0;

  26:         }

  27:     }

  28:     #endregion //GetBookCount

  29:  

  30:  

  31:     #endregion //Member Variables

  32:  

  33:     #region Methods

  34:  

  35:     #region GetBooks

  36:     /// <summary>

  37:     /// Gets the books.

  38:     /// </summary>

  39:     /// <returns></returns>

  40:     private static IEnumerable<Book> GetBooks()

  41:     {

  42:         //Return books as IEnumerable

  43:         if (doc != null)

  44:         {

  45:  

  46:             var dataSource = (from d in doc.Descendants("book")

  47:                               where (d.Descendants("chapter") != null || d.Descendants("chapter").Count() >= 0)

  48:                               select new Book

  49:                               {

  50:                                   Author = d.Attribute("Author").Value,

  51:                                   Title = d.Attribute("Title").Value,

  52:                                   UnitPrice = d.Attribute("UnitPrice").GetDecimalValue(),

  53:                                   Url = d.Attribute("Url").Value,

  54:                                   ReleaseDate = d.Attribute("ReleaseDate").Value,

  55:                                   ChaptersCount = d.Descendants("chapter").Count()

  56:                               });

  57:  

  58:             return dataSource.ToList();

  59:         }

  60:         return null;

  61:     }

  62:  

  63:     /// <summary>

  64:     /// Gets the books.

  65:     /// </summary>

  66:     /// <param name="startIndex">The start index.</param>

  67:     /// <param name="itemsCount">The items count.</param>

  68:     /// <returns></returns>

  69:     private static IEnumerable<Book> GetBooks(int startIndex, int itemsCount)

  70:     {

  71:         //Return range of books as IEnumerable

  72:         if (doc != null)

  73:         {

  74:  

  75:             var dataSource = (from d in doc.Descendants("book")

  76:                               where (d.Descendants("chapter") != null || d.Descendants("chapter").Count() >= 0)

  77:                               select new Book

  78:                               {

  79:                                   Author = d.Attribute("Author").Value,

  80:                                   Title = d.Attribute("Title").Value,

  81:                                   UnitPrice = d.Attribute("UnitPrice").GetDecimalValue(),

  82:                                   Url = d.Attribute("Url").Value,

  83:                                   ReleaseDate = d.Attribute("ReleaseDate").Value,

  84:                                   ChaptersCount = d.Descendants("chapter").Count(),

  85:                               });

  86:  

  87:  

  88:             List<Book> lst = dataSource.ToList();

  89:  

  90:             itemsCount = Math.Min(lst.Count - 1 - startIndex, itemsCount);

  91:  

  92:             return lst.GetRange(startIndex, itemsCount);

  93:         }

  94:         return null;

  95:     }

  96:     #endregion //GetBooks

  97:  

  98:     #region GetChapters

  99:  

 100:     /// <summary>

 101:     /// Gets the chapters.

 102:     /// </summary>

 103:     /// <param name="url">The URL.</param>

 104:     /// <returns></returns>

 105:     private static IEnumerable<Chapter> GetChapters(string url)

 106:     {

 107:         //Return the chapters for a specified book

 108:         if (doc != null)

 109:         {

 110:             var chapters = (from d in doc.Descendants("book")

 111:                             where

 112:                                 (d.Attribute("Url").Value.Equals(url) && d.Descendants("chapter") != null &&

 113:                                  d.Descendants("chapter").Count() > 0)

 114:                             select GetChapters(d));

 115:  

 116:             return chapters.First().ToList();

 117:         }

 118:  

 119:         return null;

 120:     }

 121:  

 122:     /// <summary>

 123:     /// Gets the chapters.

 124:     /// </summary>

 125:     /// <param name="url">The URL.</param>

 126:     /// <param name="startIndex">The start index.</param>

 127:     /// <param name="itemsCount">The items count.</param>

 128:     /// <returns></returns>

 129:     private IEnumerable<Chapter> GetChapters(string url, int startIndex, int itemsCount)

 130:     {

 131:  

 132:  

 133:         //Return the range of chapters for a specified book

 134:         if (doc != null)

 135:         {

 136:  

 137:  

 138:             var chapters = (from d in doc.Descendants("book")

 139:                             where

 140:                                 (d.Attribute("Url").Value.Equals(url) && d.Descendants("chapter") != null &&

 141:                                  d.Descendants("chapter").Count() > 0)

 142:                             select GetChapters(d).ToList());

 143:  

 144:             if (chapters.Count() > 0 && chapters.First().Count > 0)

 145:             {

 146:                 List<Chapter> lst = chapters.First();

 147:  

 148:                 List<Chapter> result = new List<Chapter>();

 149:  

 150:                 for (int i = startIndex; i < startIndex + itemsCount; i++)

 151:                 {

 152:                     try

 153:                     {

 154:                         Chapter ch = lst[i];

 155:                         result.Add(ch);

 156:                     }

 157:                     catch (Exception)

 158:                     {

 159:                         continue;

 160:                     }

 161:                 }

 162:  

 163:                 return result;

 164:                 //return lst;

 165:                 //itemsCount = Math.Min(lst.Count - 1 - startIndex, itemsCount);

 166:                 //itemsCount = Math.Min(lst.Count - startIndex, itemsCount);

 167:                 //var x1 = new Chapter[itemsCount];

 168:  

 169:                 //try

 170:                 //{

 171:                 //    lst.CopyTo(startIndex, x1, 0, itemsCount);

 172:  

 173:                 //    //return lst;

 174:  

 175:                 //    return x1;

 176:                 //}

 177:                 //catch (Exception)

 178:                 //{

 179:                 //    return null;

 180:                 //}

 181:  

 182:             }

 183:  

 184:  

 185:         }

 186:  

 187:         return null;

 188:     }

 189:  

 190:     /// <summary>

 191:     /// Gets the chapters.

 192:     /// </summary>

 193:     /// <param name="parent">The parent.</param>

 194:     /// <returns></returns>

 195:     private static IEnumerable<Chapter> GetChapters(XElement parent)

 196:     {

 197:         return (from d in parent.Descendants("chapter")

 198:                 select new Chapter

 199:                 {

 200:                     Title = d.Attribute("Title").Value

 201:                 }).ToList<Chapter>();

 202:     }

 203:  

 204:     #endregion //GetChapters

 205:  

 206:     #region GetBookDataSource

 207:     /// <summary>

 208:     /// Gets the book data source.

 209:     /// </summary>

 210:     /// <returns></returns>

 211:     [OperationContract]

 212:     public IEnumerable<Book> GetBookDataSource()

 213:     {

 214:  

 215:         return GetBooks();

 216:  

 217:     }

 218:  

 219:     /// <summary>

 220:     /// Gets the book data source.

 221:     /// </summary>

 222:     /// <param name="startIndex">The start index.</param>

 223:     /// <param name="itemsCount">The items count.</param>

 224:     /// <returns></returns>

 225:     [OperationContract(Name = "GetRangeBookDataSource")]

 226:     public IEnumerable<Book> GetBookDataSource(int startIndex, int itemsCount)

 227:     {

 228:         return GetBooks(startIndex, itemsCount);

 229:  

 230:     }

 231:  

 232:     #endregion //GetBookDataSource

 233:  

 234:     #region GetBookChapters

 235:     /// <summary>

 236:     /// Gets the book data source.

 237:     /// </summary>

 238:     /// <returns></returns>

 239:     [OperationContract]

 240:     public IEnumerable<Chapter> GetBookChapters(string url)

 241:     {

 242:         return GetChapters(url);

 243:     }

 244:  

 245:     /// <summary>

 246:     /// Gets the book chapters.

 247:     /// </summary>

 248:     /// <param name="url">The URL.</param>

 249:     /// <param name="startIndex">The start index.</param>

 250:     /// <param name="itemsCount">The items count.</param>

 251:     /// <returns></returns>

 252:     [OperationContract(Name = "GetRangeBookChapters")]

 253:     public IEnumerable<Chapter> GetBookChapters(string url, int startIndex, int itemsCount)

 254:     {

 255:         return GetChapters(url, startIndex, itemsCount);

 256:     }

 257:  

 258:     #endregion //GetBookChapters

 259:  

 260:     #endregion //Methods

 261: }

 262: #endregion //BookDataSourceService

 

Client implementation:

The client application is a Silverlight navigation application, that implements the Model-View-ViewModel design pattern (MVVM).   ViewModels uses  custom collections, that inherits VirtualCollection<T>. In the application there are two views: one with XamGrid and another with XamDataTree.

ViewModels  implementation:

Implementation is a very similar to the one used in the article “On Demand Data Loading in XamTree” 

In the BookChaptersData collection load size is a smaller – fixed to 5 items

BookChaptersData implementation

   1: #region BookChaptersData

   2: public class BookChaptersData : VirtualCollection<Chapter>

   3: {

   4:     #region Member Variables

   5:  

   6:     private int _loadSize = 5;

   7:     private int _startIndex;

   8:  

   9:     #endregion //Member Variables

  10:  

  11:     #region Constructors

  12:  

  13:     public BookChaptersData()

  14:     {

  15:         this.LoadSize = _loadSize;

  16:         this.AnticipatedCount = _itemsCount;

  17:         this.ItemDataRequested += new EventHandler<ItemDataRequestedEventArgs>(BookChaptersData_ItemDataRequested);

  18:     }

  19:  

  20:     #endregion //Constructors

  21:  

  22:     #region Properties

  23:  

  24:     #region Client

  25:     private BookDataSourceServiceClient _client;

  26:     public BookDataSourceServiceClient Client

  27:     {

  28:         get

  29:         {

  30:             if (this._client == null)

  31:             {

  32:                 this._client = new BookDataSourceServiceClient();

  33:             }

  34:             return this._client;

  35:         }

  36:         set

  37:         {

  38:             this._client = value;

  39:             this.OnPropertyChanged("Client");

  40:         }

  41:     }

  42:     #endregion //Client

  43:  

  44:     #region ChapterBook

  45:     /// <summary>

  46:     /// local variable _ChapterBook

  47:     /// </summary>

  48:     private BookViewModel _chapterBook;

  49:  

  50:     /// <summary>

  51:     /// Identifies the ChapterBook property.

  52:     /// </summary>        

  53:     public BookViewModel ChapterBook

  54:     {

  55:         get { return _chapterBook; }

  56:         set

  57:         {

  58:             _chapterBook = value;

  59:             OnPropertyChanged("ChapterBook");

  60:         }

  61:     }

  62:     #endregion  //ChapterBook

  63:  

  64:     #region ItemsCount

  65:     /// <summary>

  66:     /// local variable _ItemsCount

  67:     /// </summary>

  68:     private int _itemsCount = 5;

  69:  

  70:     /// <summary>

  71:     /// Identifies the ItemsCount property.

  72:     /// </summary>        

  73:     public int ItemsCount

  74:     {

  75:         get { return _itemsCount; }

  76:         set

  77:         {

  78:             _itemsCount = value;

  79:             this.AnticipatedCount = _itemsCount;

  80:             OnPropertyChanged("ItemsCount");

  81:         }

  82:     }

  83:     #endregion  //ItemsCount

  84:  

  85:     #endregion //Properties

  86:  

  87:     #region EventHandlers

  88:  

  89:     #region BookChaptersData_ItemDataRequested

  90:     void BookChaptersData_ItemDataRequested(object sender, ItemDataRequestedEventArgs e)

  91:     {

  92:         if (this.ChapterBook == null)

  93:         {

  94:             return;

  95:         }

  96:  

  97:         this._startIndex = e.StartIndex;

  98:  

  99:         this._client.GetRangeBookChaptersAsync(this.ChapterBook.Url, e.StartIndex, e.ItemsCount);

 100:         if (this._client != null)

 101:         {

 102:             this._client.GetRangeBookChaptersCompleted -= ClientGetRangeBookChaptersCompleted;

 103:             this._client.GetRangeBookChaptersCompleted += new EventHandler<GetRangeBookChaptersCompletedEventArgs>(ClientGetRangeBookChaptersCompleted);

 104:             

 105:         }

 106:  

 107:     }

 108:     #endregion //BookChaptersData_ItemDataRequested

 109:  

 110:     #region ClientGetRangeBookChaptersCompleted

 111:     void ClientGetRangeBookChaptersCompleted(object sender, GetRangeBookChaptersCompletedEventArgs e)

 112:     {

 113:         if (e.Result != null)

 114:         {

 115:  

 116:             this.LoadItems(this._startIndex, e.Result);

 117:  

 118:         }

 119:     }

 120:     #endregion //ClientGetRangeBookChaptersCompleted

 121:  

 122:     #endregion //EventHandlers

 123: }

 124: #endregion //BookChaptersData

In some cases when the client application needs to receive quicker data (like when expand a XamDataTreeNode with many child nodes) we could force receiving the whole data moving to the last page(last part of data) in the collection. In the BookViewModel  there is added a method GetBookChapters that receives all additional data using a VirtualCollection method MoveToLastPage().

BookViewModel implementation:

   1: #region BookViewModel

   2: public class BookViewModel : Book

   3: {

   4:     #region Constructors

   5:  

   6:     public BookViewModel()

   7:     {

   8:     }

   9:  

  10:     public BookViewModel(Book book)

  11:     {

  12:         this.Author = book.Author;

  13:         this.Title = book.Title;

  14:         this.Url = book.Url;

  15:         this.ReleaseDate = book.ReleaseDate;

  16:         this.UnitPrice = book.UnitPrice;

  17:         this.Chapters = book.Chapters;

  18:         this.ChaptersCount = book.ChaptersCount;

  19:     }

  20:     #endregion //Constructors

  21:  

  22:     #region Properties

  23:  

  24:     #region Client

  25:     private BookDataSourceServiceClient _client;

  26:     public BookDataSourceServiceClient Client

  27:     {

  28:         get

  29:         {

  30:             if (this._client == null)

  31:             {

  32:                 this._client = new BookDataSourceServiceClient();

  33:             }

  34:             return this._client;

  35:         }

  36:         set

  37:         {

  38:             this._client = value;

  39:             this.RaisePropertyChanged("Client");

  40:         }

  41:     }

  42:  

  43:     #endregion //Client

  44:  

  45:  

  46:     #region BookChapters

  47:     /// <summary>

  48:     /// local variable _bookChapters

  49:     /// </summary>

  50:     private BookChaptersData _bookChapters;

  51:  

  52:     /// <summary>

  53:     /// Identifies the Chapters property.

  54:     /// </summary>        

  55:     public BookChaptersData BookChapters

  56:     {

  57:         get

  58:         {

  59:             if (_bookChapters == null)

  60:             {

  61:                 this._bookChapters = new BookChaptersData { Client = this.Client, ItemsCount = this.ChaptersCount, ChapterBook = this };

  62:                 this.RaisePropertyChanged("BookChapters");

  63:             }

  64:             return _bookChapters;

  65:         }

  66:         set

  67:         {

  68:             _bookChapters = value;

  69:             this.RaisePropertyChanged("BookChapters");

  70:         }

  71:     }

  72:  

  73:     #endregion  //BookChapters

  74:  

  75:     #endregion //Properties

  76:  

  77:     #region Methods

  78:  

  79:     #region GetBookChapters

  80:     public void GetBookChapters(int size)

  81:     {

  82:         if (this.BookChapters != null)

  83:         {

  84:             this.BookChapters.LoadSize = size;

  85:             this.BookChapters.MoveToLastPage();

  86:             this.RaisePropertyChanged("BookChapters");

  87:         }

  88:     }

  89:     #endregion //GetBookChapters

  90:  

  91:     #endregion //Methods

  92:  

  93: }

  94: #endregion //BookViewModel

 

View model are added as static resources on the application level. To see difference for both XamDataTree and XamGrid components in the application there are used two different instances of the  BookDataVcViewModel (BookDataVcViewModel  is a ViewModel, used as DataContext for views).

   1: <Application   

   2:   x:Class="XamGridLazyLoadingDemoApp.App"

   3:   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

   4:   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 

   5:   xmlns:vm="clr-namespace:XamGridLazyLoadingDemoApp.ViewModels">

   6:  

   7:   <Application.Resources>

   8:     <ResourceDictionary>

   9:       <ResourceDictionary.MergedDictionaries>

  10:         <ResourceDictionary Source="Assets/Styles.xaml"/>

  11:       </ResourceDictionary.MergedDictionaries>

  12:     </ResourceDictionary>

  13:         <vm:BookDataViewModel x:Key="BookDataViewModel" />

  14:         <vm:BookDataVcViewModel x:Key="BookDataViewModelVC" />

  15:         <vm:BookDataVcViewModel x:Key="BookDataViewModelVC2" />

  16:     </Application.Resources>

  17:  

  18: </Application>

Views implementation:

XamGridVcLazyLoadingView implementation

Cerate a page, named XamGridVcLazyLoadingView with a XamGrid instance inside it:

   1: <Grid x:Name="LayoutRoot" DataContext="{StaticResource BookDataViewModelVC}" >

   2:     <Grid.RowDefinitions>

   3:         <RowDefinition Height="300" />

   4:         <RowDefinition/>

   5:     </Grid.RowDefinitions>

   6:     <ig:XamGrid x:Name="TestXamWebGrid"  AutoGenerateColumns="False" ItemsSource="{Binding Books}" SelectedRowsCollectionChanged="TestXamWebGrid_SelectedRowsCollectionChanged">

   7:         <ig:XamGrid.ExpansionIndicatorSettings>

   8:             <ig:ExpansionIndicatorSettings Visibility="Visible"/>

   9:         </ig:XamGrid.ExpansionIndicatorSettings>

  10:         <ig:XamGrid.SelectionSettings>

  11:             <ig:SelectionSettings  CellClickAction="SelectRow"

  12:             CellSelection="None" ColumnSelection="None"

  13:             RowSelection="Single" />

  14:         </ig:XamGrid.SelectionSettings>

  15:         <ig:XamGrid.RowSelectorSettings>

  16:             <ig:RowSelectorSettings Visibility="Visible" EnableRowNumbering="True"/>

  17:         </ig:XamGrid.RowSelectorSettings>

  18:         <ig:XamGrid.Columns>

  19:             <ig:TextColumn Key="Title" Width="200" HeaderText="Title:"/>

  20:             <ig:TextColumn Key="Author" Width="200" HeaderText="Author:"/>

  21:             <ig:TextColumn Key="UnitPrice" HeaderText="Unit Price:"/>

  22:             <ig:TextColumn Key="ChaptersCount" Width="70" HeaderText="Chapters Count:"/>

  23:             <ig:HyperlinkColumn Key="Url" Width="300" HeaderText="Url:"/>               

  24:             <ig:ColumnLayout Key="BookChapters">

  25:                 <ig:ColumnLayout.Columns>

  26:                     <ig:TextColumn Key="Title" HeaderText="Chapter Title:"/>

  27:                 </ig:ColumnLayout.Columns>                        

  28:             </ig:ColumnLayout>

  29:         </ig:XamGrid.Columns>

  30:         

  31:     </ig:XamGrid>

  32:     <Grid  Grid.Row="1" Visibility="Collapsed"

  33:               HorizontalAlignment="Stretch" Margin="0,10,0,0" Name="bookGrid" VerticalAlignment="Top">

  34:         <Grid.ColumnDefinitions>

  35:             <ColumnDefinition Width="Auto" />

  36:             <ColumnDefinition Width="Auto" />

  37:         </Grid.ColumnDefinitions>

  38:         <Grid.RowDefinitions>

  39:             <RowDefinition Height="Auto" />

  40:             <RowDefinition Height="Auto" />

  41:             <RowDefinition Height="Auto" />

  42:             <RowDefinition Height="Auto" />

  43:             <RowDefinition Height="Auto" />

  44:         </Grid.RowDefinitions>

  45:         <sdk:Label Content="Author:" Grid.Column="0" Grid.Row="0" HorizontalAlignment="Left" Margin="3" VerticalAlignment="Center" />

  46:         <TextBox Grid.Column="1" Grid.Row="0" Height="23" HorizontalAlignment="Left" Margin="3" Name="authorTextBox" Text="{Binding Path=Author, Mode=TwoWay, ValidatesOnExceptions=true, NotifyOnValidationError=true}" VerticalAlignment="Center" Width="120" />

  47:         <sdk:Label Content="Release Date:" Grid.Column="0" Grid.Row="1" HorizontalAlignment="Left" Margin="3" VerticalAlignment="Center" />

  48:         <TextBox Grid.Column="1" Grid.Row="1" Height="23" HorizontalAlignment="Left" Margin="3" Name="releaseDateTextBox" Text="{Binding Path=ReleaseDate, Mode=TwoWay, ValidatesOnExceptions=true, NotifyOnValidationError=true}" VerticalAlignment="Center" Width="120" />

  49:         <sdk:Label Content="Title:" Grid.Column="0" Grid.Row="2" HorizontalAlignment="Left" Margin="3" VerticalAlignment="Center" />

  50:         <TextBox Grid.Column="1" Grid.Row="2" Height="23" HorizontalAlignment="Left" Margin="3" Name="titleTextBox" TextWrapping="Wrap" Text="{Binding Path=Title, Mode=TwoWay, ValidatesOnExceptions=true, NotifyOnValidationError=true}" VerticalAlignment="Center"  MinWidth="120" />

  51:         <sdk:Label Content="Unit Price:" Grid.Column="0" Grid.Row="3" HorizontalAlignment="Left" Margin="3" VerticalAlignment="Center" />

  52:         <TextBox Grid.Column="1" Grid.Row="3" Height="23" HorizontalAlignment="Left" Margin="3" Name="unitPriceTextBox" Text="{Binding Path=UnitPrice, Mode=TwoWay, ValidatesOnExceptions=true, NotifyOnValidationError=true}" VerticalAlignment="Center" Width="120" />

  53:         <sdk:Label Content="Url:" Grid.Column="0" Grid.Row="4" HorizontalAlignment="Left" Margin="3" VerticalAlignment="Center" />

  54:         <TextBox Grid.Column="1" Grid.Row="4" Height="23" HorizontalAlignment="Left" Margin="3" Name="urlTextBox" Text="{Binding Path=Url, Mode=TwoWay, ValidatesOnExceptions=true, NotifyOnValidationError=true}" VerticalAlignment="Center" Width="120" />

  55:     </Grid>

  56: </Grid>

Column layouts are used to display only part of the properties from the hierarchical data.

   1: public partial class XamGridVcLazyLoadingView : Page

   2: {

   3:  

   4:     #region Constructors

   5:     public XamGridVcLazyLoadingView()

   6:     {

   7:         InitializeComponent();

   8:     }

   9:     #endregion //Constructors

  10:  

  11:     #region Methods

  12:  

  13:     #region OnNavigatedTo

  14:     // Executes when the user navigates to this page.

  15:     protected override void OnNavigatedTo(NavigationEventArgs e)

  16:     {

  17:     }

  18:     #endregion //OnNavigatedTo 

  19:  

  20:     #endregion //Methods

  21:  

  22:     #region EventHandlers

  23:  

  24:     #region TestXamWebGrid_SelectedRowsCollectionChanged

  25:     private void TestXamWebGrid_SelectedRowsCollectionChanged(object sender, Infragistics.Controls.Grids.SelectionCollectionChangedEventArgs<Infragistics.Controls.Grids.SelectedRowsCollection> e)

  26:     {

  27:  

  28:         if (e.NewSelectedItems != null && e.NewSelectedItems.Count > 0)

  29:         {

  30:             Row row = e.NewSelectedItems[0];

  31:             var book = row.Data as BookViewModel;

  32:             if (book != null)

  33:             {

  34:                 if (bookGrid.Visibility == System.Windows.Visibility.Collapsed)

  35:                 {

  36:                     bookGrid.Visibility = System.Windows.Visibility.Visible;

  37:                 }

  38:                 bookGrid.DataContext = book;

  39:                 book.GetBookChapters(book.ChaptersCount);

  40:             }

  41:         }

  42:  

  43:     }

  44:     #endregion //TestXamWebGrid_SelectedRowsCollectionChanged

  45:  

  46:     #endregion //EventHandlers

  47: }

 

First time when data is loaded there are loaded only first 5 chapters from each book where are chapters available. All other chapters are loaded part by part when a parent row is expanded. Expansion indicators are visible only for the rows, representing books with available chapters.

XamDataTreeVcLazyLoadingView implementation

Cerate a page, named XamDataTreeVcLazyLoadingView with a XamDataTree instance inside it:

   1: <Grid x:Name="LayoutRoot" DataContext="{StaticResource BookDataViewModelVC2}">

   2:     <Grid.ColumnDefinitions>

   3:         <ColumnDefinition Width="380"/>

   4:         <ColumnDefinition/>

   5:     </Grid.ColumnDefinitions>

   6:     <ig:XamDataTree x:Name="BookDataTree" NodeExpansionChanged="BookDataTree_NodeExpansionChanged" ItemsSource="{Binding Books}" SelectedNodesCollectionChanged="BookDataTree_SelectedNodesCollectionChanged" >

   7:         <ig:XamDataTree.SelectionSettings>

   8:             <ig:TreeSelectionSettings NodeSelection="Single"/>

   9:         </ig:XamDataTree.SelectionSettings>

  10:         <ig:XamDataTree.GlobalNodeLayouts>

  11:             <ig:NodeLayout Key="BookChapters" TargetTypeName="BookViewModel" DisplayMemberPath="Title"/>

  12:         </ig:XamDataTree.GlobalNodeLayouts>

  13:     </ig:XamDataTree>

  14:     <Grid Grid.Column="1">

  15:         <Grid.RowDefinitions>

  16:             <RowDefinition Height="60"/>

  17:             <RowDefinition/>

  18:         </Grid.RowDefinitions>

  19:         <StackPanel Orientation="Vertical">

  20:             <TextBlock x:Name="TxtTitleBook" >

  21:                 <Run Text="XamDataTree and VirtualCollection"/>

  22:                 <LineBreak/>

  23:                 <Run Text="lazy Loading Sample:"/>

  24:             </TextBlock>

  25:             <TextBlock x:Name="TxtSelectedBook" Text="Select Book:"/>

  26:         </StackPanel>

  27:  

  28:         <Grid Grid.Row="1" Visibility="Collapsed"

  29:               HorizontalAlignment="Stretch" Margin="0,10,0,0" Name="bookGrid" VerticalAlignment="Top">

  30:             <Grid.ColumnDefinitions>

  31:                 <ColumnDefinition Width="Auto" />

  32:                 <ColumnDefinition Width="Auto" />

  33:             </Grid.ColumnDefinitions>

  34:             <Grid.RowDefinitions>

  35:                 <RowDefinition Height="Auto" />

  36:                 <RowDefinition Height="Auto" />

  37:                 <RowDefinition Height="Auto" />

  38:                 <RowDefinition Height="Auto" />

  39:                 <RowDefinition Height="Auto" />

  40:             </Grid.RowDefinitions>

  41:             <sdk:Label Content="Author:" Grid.Column="0" Grid.Row="0" HorizontalAlignment="Left" Margin="3" VerticalAlignment="Center" />

  42:             <TextBox Grid.Column="1" Grid.Row="0" Height="23" HorizontalAlignment="Left" Margin="3" Name="authorTextBox" Text="{Binding Path=Author, Mode=TwoWay, ValidatesOnExceptions=true, NotifyOnValidationError=true}" VerticalAlignment="Center" Width="120" />

  43:             <sdk:Label Content="Release Date:" Grid.Column="0" Grid.Row="1" HorizontalAlignment="Left" Margin="3" VerticalAlignment="Center" />

  44:             <TextBox Grid.Column="1" Grid.Row="1" Height="23" HorizontalAlignment="Left" Margin="3" Name="releaseDateTextBox" Text="{Binding Path=ReleaseDate, Mode=TwoWay, ValidatesOnExceptions=true, NotifyOnValidationError=true}" VerticalAlignment="Center" Width="120" />

  45:             <sdk:Label Content="Title:" Grid.Column="0" Grid.Row="2" HorizontalAlignment="Left" Margin="3" VerticalAlignment="Center" />

  46:             <TextBox Grid.Column="1" Grid.Row="2" Height="23" HorizontalAlignment="Left" Margin="3" Name="titleTextBox" TextWrapping="Wrap" Text="{Binding Path=Title, Mode=TwoWay, ValidatesOnExceptions=true, NotifyOnValidationError=true}" VerticalAlignment="Center"  MinWidth="120" />

  47:             <sdk:Label Content="Unit Price:" Grid.Column="0" Grid.Row="3" HorizontalAlignment="Left" Margin="3" VerticalAlignment="Center" />

  48:             <TextBox Grid.Column="1" Grid.Row="3" Height="23" HorizontalAlignment="Left" Margin="3" Name="unitPriceTextBox" Text="{Binding Path=UnitPrice, Mode=TwoWay, ValidatesOnExceptions=true, NotifyOnValidationError=true}" VerticalAlignment="Center" Width="120" />

  49:             <sdk:Label Content="Url:" Grid.Column="0" Grid.Row="4" HorizontalAlignment="Left" Margin="3" VerticalAlignment="Center" />

  50:             <TextBox Grid.Column="1" Grid.Row="4" Height="23" HorizontalAlignment="Left" Margin="3" Name="urlTextBox" Text="{Binding Path=Url, Mode=TwoWay, ValidatesOnExceptions=true, NotifyOnValidationError=true}" VerticalAlignment="Center" Width="120" />

  51:         </Grid>

  52:     </Grid>

  53: </Grid>

 

When some XamDataTreeNode instance, representing a book was expanded, all additional data for the book chapters is loaded from the server, calling GetBookChapters method:

   1: #region XamDataTreeVcLazyLoadingView

   2: public partial class XamDataTreeVcLazyLoadingView : Page

   3: {

   4:     #region Constructors

   5:     public XamDataTreeVcLazyLoadingView()

   6:     {

   7:         InitializeComponent();

   8:     }

   9:     #endregion //Constructors

  10:  

  11:     #region Methods

  12:     #region OnNavigatedTo

  13:     /// <summary>

  14:     /// Called when a page becomes the active page in a frame.

  15:     /// </summary>

  16:     /// <param name="e">An object that contains the event data.</param>

  17:     protected override void OnNavigatedTo(NavigationEventArgs e)

  18:     {

  19:     }

  20:     #endregion //OnNavigatedTo 

  21:     #endregion //Methods

  22:  

  23:     #region EventHandlers

  24:     #region BookDataTree_SelectedNodesCollectionChanged

  25:     private void BookDataTree_SelectedNodesCollectionChanged(object sender, Infragistics.Controls.Menus.NodeSelectionEventArgs e)

  26:     {

  27:  

  28:         if (e.CurrentSelectedNodes != null && e.CurrentSelectedNodes.Count > 0)

  29:         {

  30:             XamDataTreeNode node = e.CurrentSelectedNodes[0];

  31:  

  32:             var book = node.Data as BookViewModel;

  33:             if (book != null)

  34:             {

  35:                 if (bookGrid.Visibility == System.Windows.Visibility.Collapsed)

  36:                 {

  37:                     bookGrid.Visibility = System.Windows.Visibility.Visible;

  38:                 }

  39:                 bookGrid.DataContext = book;

  40:             }

  41:         }

  42:  

  43:     }

  44:     #endregion //BookDataTree_SelectedNodesCollectionChanged

  45:  

  46:     #region BookDataTree_NodeExpansionChanged

  47:     private void BookDataTree_NodeExpansionChanged(object sender, NodeExpansionChangedEventArgs e)

  48:     {

  49:         XamDataTreeNode node = e.Node;

  50:         if (node != null && node.IsExpanded)

  51:         {

  52:             var book = node.Data as BookViewModel;

  53:             if (book != null)

  54:             {

  55:                 book.BookChapters.LoadSize = book.ChaptersCount;

  56:                 book.GetBookChapters(book.ChaptersCount);

  57:             }

  58:         }

  59:  

  60:     }

  61:     #endregion //BookDataTree_NodeExpansionChanged 

  62:     #endregion //EventHandlers

  63:  

  64: }

  65: #endregion //XamDataTreeVcLazyLoadingView

 

Run the application:

The home page is a XamGridVcLazyLoadingView.
Data for the visible rows is loaded. Only first 5 chapters for books where is available data for book chapters are loaded. This is enough to recognize where are child records via expansion indicators.

XamGridLazyLoading_Pic04

Select a row. Data for the selected book is visible below the XamGrid.

XamGridLazyLoading_Pic05

Expand the selected row. Only data for the visible rows will be loaded.

XamGridLazyLoading_Pic06

Scroll down to see other chapters. Data is loaded part by part.

XamGridLazyLoading_Pic07

Select a page  “XamDataTree with VirtualCollection” ( XamDataTreeVcLazyLoadingView ).

XamGridLazyLoading_Pic08

Select some node – data for the selected book is visible right the XamDataTree.

XamGridLazyLoading_Pic09

Expand the selected node – all additional data for the book chapters is loaded.

XamGridLazyLoading_Pic10

Sample code could be downloaded here:

About Mihail Mateev

am a Microsoft Regional Director currently living in Sofia, Bulgaria. My interests range from technology to entrepreneurship. I am also interested in programming, web development, and education. Technical Consultant, Community enthusiast, PASS Regional Mentor for Central Eastern Europe, chapter lead, Microsoft MVP – Microsoft Azure. Organizer of SQLSaturday, Azure Bootcamp, IoT and JavaScript conferences. My experience is in various areas related to Microsoft technologies, including Windows Platform, ASP.Net MVC, MS SQL Server and Microsoft Azure. I have a PhD in cloud computing and am a university lecturer on Smart Homes and Smart Energy IoT Solutions
This entry was posted in Uncategorized. Bookmark the permalink.

1 Response to On Demand Data Loading in XamGrid and XamDataTree

  1. Spot on with this write-up, I seriously believe that this amazing site
    needs far more attention. I’ll probably be back again to read more, thanks for the info!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s