It would be great for AdvancedCollectionView to implement ICollectionView.CollectionGroups, based on item's IGrouping, just like the default view implementation of CollectionViewSource does.
This would allow using groping and incremental loading together, which CollectionViewSource doesn't support.
Currently I'm working on inheriting from AdvancedCollectionView and redefining CollectionGroups, to see how far I can go with this scenario.
Thanks for submitting a new feature request! I've automatically added a vote 馃憤 reaction to help get things started. Other community members can vote to help us prioritize this feature in the future!
This issue has been marked as "needs attention 馃憢" due to no activity for 15 days. Please triage the issue so the fix can be established.
This issue has been marked as "needs attention 馃憢" due to no activity for 15 days. Please triage the issue so the fix can be established.
This issue has been marked as "needs attention 馃憢" due to no activity for 15 days. Please triage the issue so the fix can be established.
This issue has been marked as "needs attention 馃憢" due to no activity for 15 days. Please triage the issue so the fix can be established.
This issue has been marked as "needs attention 馃憢" due to no activity for 15 days. Please triage the issue so the fix can be established.
@ianier Have you been able to investigate this addition?
I finally inherited from IncrementalLoadingCollection and implemented ICollectionViewFactory.CreateView() to do my own grouping (ICollectionView.CollectionGroups), inheriting from AdvancedCollectionView. Grouping is done with a simple delegate, which proved easier to do than my original idea.
At the moment I don't have time to work on a PR, but here's the code of my collection view in cased someone wants to have a look:
public class AdvancedCollectionViewEx : AdvancedCollectionView, ICollectionView
{
private class CollectionViewGroup : ICollectionViewGroup
{
public ObservableVector<object> Items { get; }
public object Group { get; }
public IObservableVector<object> GroupItems => Items;
public CollectionViewGroup(object group)
{
Group = group;
Items = new ObservableVector<object>();
}
}
public Func<object, object> Group { get; }
private ObservableVector<object> _collectionGroups;
// The CollectionGroups property is of type IObservableVector;, but these objects should implement ICollectionViewGroup.
IObservableVector<object> ICollectionView.CollectionGroups
{
get { return _collectionGroups; }
}
public AdvancedCollectionViewEx(IList source, Func<object, object> group) : base(source)
{
if (group != null)
{
Group = group;
_collectionGroups = new ObservableVector<object>();
RebuildGroups();
VectorChanged += HandleViewChanges;
}
}
private void RebuildGroups()
{
_collectionGroups.IsVectorChangedDeferred = true;
try
{
_collectionGroups.Clear();
if (Source != null)
{
foreach (var item in Source)
{
AddGroupedItem(item);
}
}
}
finally
{
// trigger any changes for children
foreach (CollectionViewGroup col in _collectionGroups)
{
col.Items.IsVectorChangedDeferred = false;
}
// then trigger any changes for self
_collectionGroups.IsVectorChangedDeferred = false;
}
}
private void AddGroupedItem(object item)
{
// classify the item
object key = GetItemGroup(item);
// find the group the item belongs to
var col = _collectionGroups.Cast<CollectionViewGroup>().FirstOrDefault(g => Comparer.Default.Compare(g.Group, key) == 0);
// if not found, create the item
if (col == null)
{
col = new CollectionViewGroup(key);
_collectionGroups.Add(col);
}
// propagate change deferral
col.Items.IsVectorChangedDeferred = _collectionGroups.IsVectorChangedDeferred;
// add the item to the collection
col.GroupItems.Add(item);
}
private void RemoveGroupedItem(object item)
{
foreach (CollectionViewGroup g in _collectionGroups)
{
// propagate change deferral
g.Items.IsVectorChangedDeferred = _collectionGroups.IsVectorChangedDeferred;
// actually remove the item
g.Items.Remove(item);
}
}
private object GetItemGroup(object item)
{
return Group?.Invoke(item);
}
private void HandleViewChanges(IObservableVector<object> sender, IVectorChangedEventArgs args)
{
int ndx = (int)args.Index;
switch (args.CollectionChange)
{
case CollectionChange.ItemChanged:
RemoveGroupedItem(this[ndx]);
AddGroupedItem(this[ndx]);
break;
case CollectionChange.ItemInserted:
AddGroupedItem(this[ndx]);
break;
case CollectionChange.ItemRemoved:
RebuildGroups();
break;
case CollectionChange.Reset:
RebuildGroups();
break;
}
}
}
This issue has been marked as "needs attention 馃憢" due to no activity for 15 days. Please triage the issue so the fix can be established.
This issue has been marked as "needs attention 馃憢" due to no activity for 15 days. Please triage the issue so the fix can be established.
This issue has been marked as "needs attention 馃憢" due to no activity for 15 days. Please triage the issue so the fix can be established.
This issue has been marked as "needs attention 馃憢" due to no activity for 15 days. Please triage the issue so the fix can be established.
This issue has been marked as "needs attention 馃憢" due to no activity for 15 days. Please triage the issue so the fix can be established.
This issue has been marked as "needs attention 馃憢" due to no activity for 15 days. Please triage the issue so the fix can be established.
This issue has been marked as "needs attention 馃憢" due to no activity for 15 days. Please triage the issue so the fix can be established.
This issue has been marked as "needs attention 馃憢" due to no activity for 15 days. Please triage the issue so the fix can be established.
This issue has been marked as "needs attention 馃憢" due to no activity for 15 days. Please triage the issue so the fix can be established.
This issue has been marked as "needs attention 馃憢" due to no activity for 15 days. Please triage the issue so the fix can be established.
This issue has been marked as "needs attention 馃憢" due to no activity for 15 days. Please triage the issue so the fix can be established.
This issue has been marked as "needs attention 馃憢" due to no activity for 15 days. Please triage the issue so the fix can be established.
Thanks @ianier, I think the ask here is basically the same as #1128 and have ACV support grouping, right?
Appreciate your code hint here too. We'll see if we can get a community member to pick this up and see if we can work this all together somehow.
@michael-hawker: Yes, this is a subset of #1128. I've been using the code above in my app for a while and it works well. IMO, the idea of using a delegate at the collection level (as opposed to having to implement IGrouping on the item) makes it easier to use.
@vgromfeld @Sergio0694 can we also use the new grouping stuff we added to help in this case as well?
@Vijay-Nirmal was interested in trying to help out with improvements to the AdvancedCollectionView, so hoping we can pool all this knowledge together to find a general solution we can have in the Toolkit?
Yes, looking only at the high level, it seems that there is some overlap with what has been done in ObservableGroup.
Potentially related - I'm probably missing something here but I'm a bit confused about the AdvancedCollectionView type 馃
As in, shouldn't the collection types be only using .NET Standard 2.0 APIs so that they can used in a shared backend, with all the platform-specific code being deferred to some platform-specific wrapper of sorts?
For instance, what I've been doing in my apps is this:
ObservableGroupedCollection<TKey, TValue> in my shared viewmodelsCollectionViewSource that takes that collection as inputIt's that CollectionViewSource then that automatically subscribes to all the various events and exposes the necessary views and collection groups to the UI - the backend doesn't need to care about that. Eg. if you add, remove or move items in the backing grouped collection, that CollectionViewSource will automatically relay those changes to the UI.
Here's an example in my app Legere, where I'm using this for the grouped collection of subscribed subreddits. The viewmodel is exposing an observable grouped collection, and the view is binding to the view and collection groups in a SemanticZoom control through a CollectionViewSource, which can entirely be created in XAML (or setup with an attached property):

What I'm thinking is, shouldn't we actually try to pull as much stuff as possible away from platform-specific code, and possibly add this functionality either directly over the existing .NET Standard collections as extension methods, or through a more advanced type inheriting from them and adding the extra logic I see here for eg. supporting incremental loading and whatnot?
Just thinking out loud here, as I said I might very well be missing something obvious 馃槃
This may be a case where we just need a good sample which shows how these different elements fit together:
If we can get all those things to work together, we can either realize that we don't need stuff, re-organize what we have, or build the right stuff to make that happen.
We definitely want to make it easy to connect the base collection that the developer manages to the UI layer, and @Sergio0694 I think that's where we've thought in the past having the single AdvancedCollectionView would be a single entity to broker all these aspects of the process.
However, we also haven't stepped back and looked at the architecture as a whole to figure out what makes sense to build. @Sergio0694 I think you're basically suggesting that we make sure we can build all these individual components in a platform-agnostic way, but still have them work harmoniously together?
"I think you're basically suggesting that we make sure we can build all these individual components in a platform-agnostic way, but still have them work harmoniously together?"
Exactly 馃槉
I'm all in for offering helpers (either through dedicated types or extension methods) to facilitate scenarios with specific operations such as filtering, grouping and whatnot. My main issue here is that this collection type seems to at least in part be mirroring the same functionality being offered by the CollectionViewSource type, and also the fact that this collection has strong dependencies on UI-specific types, so it's impossible to use it in your backend, if you have viewmodels in a separate .NET Standard project. As in, operations such as filtering or loading paged items should only be a concern of your viewmodels, so the collection type supporting this feature shouldn't depend on platform specific types, otherwise it makes it impossible to use it in a shared backend 馃