Here's an example of keeping the overlap between loaded CXML collections, instead of replacing the entire collection. Since there are animations when adding and removing objects, it looks pretty nice. Useful when requesting more/partial data from the server/backend. (Of course, this has nothing to do with "fading collections/items" when zooming.)
The most interesting code would be in KeepIntersection(this ICollection<PivotViewerItem> currentItems, CxmlCollectionSource newItems)
, which modifies the collection by adding and removing only the differences from the old and the new collections.
Based on Silverlight 5 PivotViewer's ObservableCollection
as per Tony Champions's and Chris Arnold's tutorials/posts.
MainPageViewModel.cs
private void CxmlCollectionSource_StateChanged(object sender, CxmlCollectionStateChangedEventArgs e)
{
// TODO: check other states
switch (e.NewState)
{
case CxmlCollectionState.Loaded:
{
var collection = sender as CxmlCollectionSource;
Debug.Assert(collection != null, "collection != null");
// TODO: don't add/remove, replace the entire list after diffing
if (!this.pivotProperties.Any())
{
// TODO: diffing algorithm for properties, minimal changes
foreach (var pivotViewerProperty in collection.ItemProperties)
{
this.pivotProperties.Add(pivotViewerProperty);
}
}
this.pivotViewerItems.KeepIntersection(collection);
break;
}
}
}
ICollection{PivotViewerItem}Extensions.cs
namespace SilverlightPivotViewer.Extensions
{
#region Using directives
using System.Collections.Generic;
using System.Linq;
using System.Windows.Controls.Pivot;
#endregion
public static class ICollectionPivotViewerItemExtensions
{
#region Public Methods and Operators
public static void KeepIntersection(
this ICollection<PivotViewerItem> currentItems, CxmlCollectionSource newItems)
{
RemoveCurrentUniqueItems(currentItems, newItems);
AddNewUniqueItems(currentItems, newItems);
}
#endregion
#region Methods
private static void AddNewUniqueItems(ICollection<PivotViewerItem> currentItems, CxmlCollectionSource newItems)
{
IEnumerable<PivotViewerItem> onlyInNewCollection =
newItems.Items.Where(pivotViewerItem => currentItems.All(i => i.Id != pivotViewerItem.Id));
foreach (var pivotViewerItem in onlyInNewCollection)
{
currentItems.Add(pivotViewerItem);
}
}
private static void RemoveCurrentUniqueItems(
ICollection<PivotViewerItem> currentItems, CxmlCollectionSource newItems)
{
IEnumerable<PivotViewerItem> onlyInCurrentCollection =
currentItems.Where(pivotViewerItem => newItems.Items.All(i => i.Id != pivotViewerItem.Id));
// Need to produce a list, otherwise it will crash (concurrent looping and editing the IEnumerable, or something related)
var onlyInCurrentCollectionList = onlyInCurrentCollection.ToList();
foreach (var pivotViewerItem in onlyInCurrentCollectionList)
{
currentItems.Remove(pivotViewerItem);
}
}
#endregion
}
}
- Coded custom diffing functions, but I'm sure someone has an awesome library doing just that.
- Thought of adding diffing for facet categories too, but it's not built for it. I guess the recommended way is to make sure the client knows about all available categories, so they can be used for filtering.