// Generate sub-group based on property equality void GroupBy(INTERNAL_PropertyGroupDescription operation) { List <Collection <object> > childGroups = new List <Collection <object> >(); foreach (object item in Items) { bool find = false; foreach (Collection <object> child in childGroups) { if (Object.Equals(GetValue(child[0], operation), GetValue(item, operation))) { child.Add(item); find = true; break; } } if (!find) { childGroups.Add(new Collection <object>()); childGroups[childGroups.Count - 1].Add(item); } } foreach (Collection <object> child in childGroups) { INTERNAL_CollectionViewGroupInternal newView = new INTERNAL_CollectionViewGroupInternal(child, this, _operations, _level + 1); _operations.Requester.AddView(newView); // create child branch (level matter in grouping views) } }
//Returns a value that indicates if a specified item has passed the filter public bool PassesFilter(object item) { INTERNAL_CollectionViewGroupInternal filterView = GetFilterView(); if (filterView != null) { return(filterView.Items.Contains(item)); } return(true); // if no filter, we consider the filter as passed }
// Take the result of the parent and generate the result for the next operation internal INTERNAL_CollectionViewGroupInternal(ICollection <object> source, INTERNAL_CollectionViewGroupInternal parent, INTERNAL_Operations operations, int level = 0) { Items = source; _level = level; _parentView = parent; _operations = operations; object operationToDo = _operations.HandleNextOperation(_level); ExecuteOperation(operationToDo); }
// Sort the data source with a default comparer void Sort(PropertySortDescription operation) { if (VerifyComparable(operation))// if we can't compare data, we don't try to sort { ListSortDirection directionBackup = operation.Direction; operation.Direction = _operations.GetFixedDirection(operation); Collection <object> childItems = new Collection <object>(); //todo: replace with a sort algorithm that is O(NLogN), for example by creating a List<T> and calling List<T>.Sort(comparer). foreach (object item in Items) { int index; // we get the value of the sorting property on this item to allow comparison (if we are here, we know that data is comparable) // then we get the position where we need to insert this item #if OPENSILVER if (true) #elif BRIDGE if (CSHTML5.Interop.IsRunningInTheSimulator) #endif { IComparable value = (IComparable)GetValue(item, operation); index = GetPosIndex_SimulatorOnly(operation, value, 0, childItems.Count, childItems); } else { dynamic value = GetValue(item, operation); index = GetPosIndex_JSOnly(operation, value, 0, childItems.Count, childItems); } childItems.Insert(index, item); } operation.Direction = directionBackup; // Pass the result of the sort to a child CollectionViewGroup in order to apply other operations (such as sort) if any: INTERNAL_CollectionViewGroupInternal newView = new INTERNAL_CollectionViewGroupInternal(childItems, this, _operations); _operations.Requester.AddView(newView); // create child branch after sorting operation } else { INTERNAL_CollectionViewGroupInternal newView = new INTERNAL_CollectionViewGroupInternal(Items, this, _operations); _operations.Requester.AddView(newView); // create child branch without sorting } }
// Filter the data source with a predicate void Filter(Predicate <Object> predicate) { // Create a new collection with the result of the filtering: Collection <object> childItems = new Collection <object>(); foreach (object obj in Items) { if (predicate(obj)) { childItems.Add(obj); } } // Pass the result of the filtering to a child CollectionViewGroup in order to apply other operations (such as sort) if any: INTERNAL_CollectionViewGroupInternal newView = new INTERNAL_CollectionViewGroupInternal(childItems, this, _operations); _operations.Requester.AddView(newView); // create child branch }
// create all the operation tree with a new source void CreateTree() { _views.Clear(); _operations = new INTERNAL_Operations(this); // we reset the operations to do ICollection <object> newCollection = new Collection <object>(); foreach (object obj in _originalDataSource) { newCollection.Add(obj); } INTERNAL_CollectionViewGroupInternal treeRoot = new INTERNAL_CollectionViewGroupInternal(newCollection.ToList <object>(), null, _operations); _views.Add(treeRoot); // we make sure that the treeRoot is the last element to be added to the _views collection because the call to the CollectionViewGroupInternal contructor creates a tree via recursion, which by itself adds the branches in _views. ConstrainIndexToRemainInsideAllowedRange(); // because some leaves can disappear if it's not the first generation (ie. if it has already been refreshed once) }
// Filter the data source using an event (the user sets e.Accepted to true or false in the event handler): void Filter(FilterEventHandler logicMethod) { // Create a new collection with the result of the filtering: Collection <object> childItems = new Collection <object>(); foreach (object obj in Items) { FilterEventArgs args = new FilterEventArgs(obj); logicMethod(this, args); if (args.Accepted) { childItems.Add(obj); } } // Pass the result of the filtering to a child CollectionViewGroup in order to apply other operations (such as sort) if any: INTERNAL_CollectionViewGroupInternal newView = new INTERNAL_CollectionViewGroupInternal(childItems, this, _operations); _operations.Requester.AddView(newView); // create child branch }
// add a new child view in the paged collection (not necessarily a leaf) internal void AddView(INTERNAL_CollectionViewGroupInternal view) { _views.Add(view); }