Vincent
Vincent

Reputation: 1547

Sorting CollectionViewSource grouping by external dictionary

I've got some component objects in a CollectionViewSource i need to sort, these objects all have a custom type. The grouping is done on the type and the components are sorted by their name. What I now need to do is sort the grouping on the component type But i need to sort these component types depending on an external source, So the objects looks a bit like this:

public class ComponentType
{
    public Guid Identification
    {
        get;
    }
}

public class Component
{
    public string Name
    {
        get;
    }

    public ComponentType Type
    {
        get;
    }
}

The collection view is created like so:

this.ComponentCollection = new CollectionViewSource();
this.ComponentCollection.Source = this.Components;
this.ComponentCollection.GroupDescriptions.Clear();
this.ComponentCollection.GroupDescriptions.Add(new PropertyGroupDescription("ComponentType"));
this.ComponentCollection.SortDescriptions.Clear();
this.ComponentCollection.SortDescriptions.Add(new SortDescription("Name", ListSortDirection.Ascending));
this.ComponentCollection.Filter += this.FilterComponent;
this.ComponentCollection.View.Refresh();
RaisePropertyChanged(() => this.ComponentCollection);

I also have the following dictionary in the same calss i'm creating the CollectionViewSource which looks like this:

public Dictionary<Guid, int> ComponentTypePositions

Where the key is the identificaiton of the component type and int is the position of which type should come first.

It is not possible to put the position as a property in the ComponentType or Component class, it needs to be a separate list.

How do i sort the grouping according to the corresponding number in the ComponentTypePositions dictionary?

Upvotes: 0

Views: 234

Answers (1)

Anateus
Anateus

Reputation: 447

You need to create a new type based on Component class which includes your position numbers and use this for the elements of your source list. This can be done inline with an anonymous type:

ComponentCollection = new CollectionViewSource();
ComponentCollection.Source = (from c in Components
                              select new
                              {
                                  Name = c.Name,
                                  Type = c.Type,
                                  Pos = ComponentTypePositions[c.Type.Identification]
                              }).ToList();
ComponentCollection.GroupDescriptions.Clear();
ComponentCollection.GroupDescriptions.Add(new PropertyGroupDescription("Type"));
ComponentCollection.SortDescriptions.Clear();
ComponentCollection.SortDescriptions.Add(new SortDescription("Pos", ListSortDirection.Ascending));
ComponentCollection.SortDescriptions.Add(new SortDescription("Name", ListSortDirection.Ascending));
ComponentCollection.Filter += FilterComponent;
ComponentCollection.View.Refresh();

If your source list need to be editable, you can use your own custom list type for it:

public class ComponentListElement
{
    private Component comp;

    public ComponentListElement(Component comp, Dictionary<Guid, int> positionMap)
    {
        this.comp = comp;
        this.Pos = positionMap[comp.Type.Identification];
    }

    public string Name { get { return comp.Name; } }
    public ComponentType Type { get { return comp.Type; } }
    public int Pos { get; private set; }
}

public class ComponentList : Collection<ComponentListElement>
{
    private Dictionary<Guid, int> positionMap;

    public ComponentList(Dictionary<Guid, int> positionMap)
    {
        this.positionMap = positionMap;
    }

    public void Add(Component item)
    {
        base.Add(new ComponentListElement(item, positionMap));
    }
}

And use it like this:

ComponentList componentList = new ComponentList(ComponentTypePositions);
foreach (var item in Components)
{
    componentList.Add(item);
}
ComponentCollection.Source = componentList;

Upvotes: 1

Related Questions