0

I have a List of flat ViewModels.

var initialList = new List<ViewModel>
{
    new ViewModel { OuterCaption = "A outer", InnerCaption = "A inner", Caption = "E", Id = 8},
    new ViewModel { OuterCaption = "B outer", InnerCaption = "B inner", Caption = "A", Id = 5},
    new ViewModel { OuterCaption = "A outer", InnerCaption = "B inner", Caption = "A", Id = 12},
    new ViewModel { OuterCaption = "B outer", InnerCaption = "B inner", Caption = "B", Id = 9},
    new ViewModel { OuterCaption = "A outer", InnerCaption = "B inner", Caption = "B", Id = 23},
    new ViewModel { OuterCaption = "B outer", InnerCaption = "C inner", Caption = "A", Id = 10},
    new ViewModel { OuterCaption = "A outer", InnerCaption = "B inner", Caption = "C", Id = 16},
    new ViewModel { OuterCaption = "A outer", InnerCaption = "A inner", Caption = "C", Id = 4},
    new ViewModel { OuterCaption = "A outer", InnerCaption = "A inner", Caption = "D", Id = 7},
    new ViewModel { OuterCaption = "C outer", InnerCaption = "A inner", Caption = "A", Id = 31},
    new ViewModel { OuterCaption = "B outer", InnerCaption = "A inner", Caption = "A", Id = 19},
    new ViewModel { OuterCaption = "B outer", InnerCaption = "A inner", Caption = "B", Id = 20},
    new ViewModel { OuterCaption = "A outer", InnerCaption = "A inner", Caption = "A", Id = 1},
    new ViewModel { OuterCaption = "A outer", InnerCaption = "A inner", Caption = "B", Id = 3}
}.OrderBy(vm => vm.OuterCaption).ThenBy(vm => vm.InnerCaption).ThenBy(vm => vm.Caption);

Where each ViewModel is as the following.

class ViewModel
{
    public string OuterCaption { get; set; }
    public string InnerCaption { get; set; }
    public string Caption { get; set; }
    public int Id { get; set; }

}

Now I want to group the List by the OuterCaption and later by the InnerCaption. I can group the List by the OuterCaption like this.

var list = initialList.GroupBy(vm => vm.OuterCaption).ToList();

And use it in my View like this and use GroupBy within my View.

foreach (var outerGrouping in list)
{
    Console.WriteLine(outerGrouping.Key);
    Console.WriteLine("~~~~~~~~~~~~~~~~~~");

    foreach (var innerGrouping in outerGrouping.GroupBy(vm => vm.InnerCaption))
    {
        Console.WriteLine(innerGrouping.Key);

        foreach (var vm in innerGrouping)
        {
            Console.WriteLine("Caption: " + vm.Caption + " Id:" + vm.Id);
        }

        Console.WriteLine("------------------");
    }

    Console.WriteLine("~~~~~~~~~~~~~~~~~~");
}

But I'd like to create a IGrouping within a IGrouping and not use GroupBy (or Linq) in my View. I do think that I should create something like IReadOnlyList<IGrouping<string, IGrouping<string, ViewModel>>> (might be wrong) for my View. How do I achieve this with my initialList so I can remove Linq from my View?

Here is the example code: https://dotnetfiddle.net/hP2kxO

julian.a
  • 1,163
  • 2
  • 9
  • 21
  • 1
    It's perfectly fine to perform grouping on flat data inside a view in order to present that data in the specific form the view is designed to represent. On contrary, the controller should probably not know about that specific form, and consequently not try to pre-group the data in a specific way that it knows the view will require, it would break the separation of concerns principle. – GSerg May 28 '21 at 10:45
  • Does this answer your question? [GroupBy with multiple groups as a hierarchy](https://stackoverflow.com/q/3435315/11683) – GSerg May 28 '21 at 10:51
  • I'm going to use Linq within my view as you suggested. I posted the solution for my question down below. – julian.a May 28 '21 at 11:32

1 Answers1

0

This is working. It's not exactly what I'm looking for but it removes Linq from my View.

var list = initialList
    .GroupBy(vm => (vm.OuterCaption, ViewModel: vm))
    .GroupBy(group => group.Key.ViewModel.InnerCaption)
    .ToList();
julian.a
  • 1,163
  • 2
  • 9
  • 21