I found that Sam's solution worked, but found that he was sorting when all the views were added to the scope, thus sorting the views twice.
Despite the fact that this is still a valid solution, after reading this post in the Prism discussion, I thought about how to implement this only when the region was loaded, but before all the views were added yet.
1 - Subscribe to CollectionChanged of Regions
I put this in the ViewModel shell code, which is associated with a view that contains the area I want to sort. Whenever importing IRegionManager was allowed, I subscribe to the CollectionChanged event in its collection of regions:
this._regionManager.Regions.CollectionChanged += new NotifyCollectionChangedEventHandler(Regions_CollectionChanged);
2 - Change the region's SortComparison to delegate deletion
Then the Regions_CollectionChanged delegate will be executed whenever the Collection of Regions is updated and SortComparison changes my desired area:
void Regions_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) { if (e.Action == NotifyCollectionChangedAction.Add) { foreach (var o in e.NewItems) { IRegion region = o as IRegion; if (region != null && region.Name == RegionNames.NavigationRegion) { region.SortComparison = CompareNavigatorViews; } } } }
3 - Define a CompareNavigatorViews delegate
In my case, I just sort the views by the assembly header where they are contained, you can implement your own comparison method here. Remember that the objects you get here are Views, not ViewModels.
private static int CompareNavigatorViews(object x, object y) { if (x == null) if (y == null) return 0; else return -1; else if (y == null) return 1; else { AssemblyInfo xAssemblyInfo = new AssemblyInfo(Assembly.GetAssembly(x.GetType())); AssemblyInfo yAssemblyInfo = new AssemblyInfo(Assembly.GetAssembly(y.GetType())); return String.Compare(xAssemblyInfo.Title, yAssemblyInfo.Title); } }
Just in case someone asks, the AssemblyInfo class is the utility class that I created. To get the name of the assembly, you can use this function:
string GetAssemblyTitle(Assembly assembly) { object[] attributes = assembly.GetCustomAttributes(typeof(AssemblyTitleAttribute), false); if (attributes.Length == 1) { return (attributes[0] as AssemblyTitleAttribute).Title; } else { // Return the assembly name if there is no title return this.GetType().Assembly.GetName().Name; } }
Hope this helps someone!