0

So the beginning of my View is

@foreach ( var G in ViewBag.GroupedBySec )
{
<div class="row">
    <div class="col-xs-12 col-sm-12 col-md-12 col-lg-12">
        <table class="table table-striped assessment-table">
            <tbody>
                <tr>
                    <td class="black-n-white" colspan="4">@G.Key</td>
                </tr>
                <tr>
                    <td>Section</td><td>Component</td><td>Completeness Level (0-100%)</td><td>Readines</td>
                </tr>
                @var GroupedBySubsection = G.GroupBy(x => x.SubsectionTitle);
                @foreach ( var g in GroupedBySubsection )
                {
                    @foreach ( var qa in g )
                    {

and I'm getting errors on the

@var GroupedBySubsection = G.GroupBy(x => x.SubsectionTitle);
@foreach ( var g in GroupedBySubsection )

lines which say

The name 'var' does not exist in the current context

and

The name 'GroupedBySection' does not exist in the current context

Any idea what I'm doing wrong?

Alternatively, any suggestions for how I can get a C# object that has the entire groupings and subgroupings so that I don't have to write all this crap in my View?

My Controller method for this page is like

    [HttpGet]
    public ActionResult Peek ( Guid pid )
    {
        ViewBag.PartnerId = pid;
        List<AnswerInfo> AllAnswers = this._Db.GetAnswersByPartner(pid);
        ViewBag.GroupedBySec = AllAnswers.GroupBy(A => A.SectionTitle);
        return View();
    }
user5648283
  • 5,913
  • 4
  • 22
  • 32
  • `@{ var GroupedBySubsection = G.GroupBy(x => x.SubsectionTitle); }` –  Feb 05 '16 at 04:55
  • And create a view model _so that I don't have to write all this crap in my View_ –  Feb 05 '16 at 04:56
  • @StephenMuecke That causes a `Cannot use a lamba experssion as an argument to a dynamically dispatched ...` on the `x => x.SubsectionTitle` – user5648283 Feb 05 '16 at 05:07
  • Give me 10 min and I'll test it :) –  Feb 05 '16 at 05:13
  • I cannot repeat that error, but what is `G`? Your `foreach` loop suggests its a object, not a collection so it would not have a `GroupBy()` method. Are you already doing some grouping in the controller? –  Feb 05 '16 at 05:19
  • @StephenMuecke Yes, I do the first set of grouping in my controller – user5648283 Feb 05 '16 at 05:23
  • 1
    OK, now I understand - `G` is `dynamic` so you need to cast it - e.g. `@{ var GroupedBySubsection = ((IEnumerable)G).GroupBy(x => x.SubsectionTitle); }` making you view even uglier :) - Use a view model. –  Feb 05 '16 at 05:33
  • Have just seen your next question. Is there any point me adding an answer and showing you how to do the view model and linq query in the controller? –  Feb 05 '16 at 06:59
  • @StephenMuecke I would be eternally greatful if you could convince me to use a view model – user5648283 Feb 05 '16 at 07:05
  • Need a break, but I'll add something in an hour - after which your going to kick yourself :) –  Feb 05 '16 at 07:10

1 Answers1

2

Your error occurs because your missing the braces around your var statement. It should be

@{ var GroupedBySubsection = G.GroupBy(x => x.SubsectionTitle); }

This will then throw a different error because you referring an item in ViewBag which is dynamic so you need to cast it as follows

@{ var GroupedBySubsection = ((IEnumerable<yourModel>)G).GroupBy(x => x.SubsectionTitle); }

making your view even uglier.

how I can get a C# object that has the entire groupings and subgroupings so that I don't have to write all this crap in my View?

Use a view model. Based on some of your previous question, you have a data model which (abbreviated) is

public class Answer
{
    public string Section { get; set; }
    public string SubSection { get; set; }
    public int QuestionID { get; set; }
    public string QuestionText { get; set; }
    ....
}

And that you want to group it in the view by Section and then SubSection. Your view models would then be

public class SectionVM
{
    public string Title{ get; set; }
    public List<SubSectionVM> SubSections { get; set; }
}
public class SubSectionVM
{
    public string Title { get; set; }
    public List<QuestionVM> Questions { get; set; }
}
public class QuestionVM
{
    public int QuestionID { get; set; }
    public string QuestionText { get; set; }
    ....
}

Your controller code would then be

var answers = db.Answers..... // your previous query

List<SectionVM> model = answers.GroupBy(x => x.Section).Select(x => new SectionVM
{
    Title = x.Key,
    SubSections = x.GroupBy(y => y.SubSection).Select(y => new SubSectionVM
    {
        Title = y.Key,
        Questions = y.Select(z => new QuestionVM
        {
            QuestionID = z.QuestionID,
            QuestionText = z.QuestionText,
            ....
        }).ToList()
    }).ToList()
}).ToList();
return View(model);

and in the view

@model List<SectionVM>
@foreach(var section in Model)
{
    <h2>@section.Title</h2>
    foreach(var subSection in section.SubSections)
    {
        <h3>@subSection.Title</h3>
        foreach(var question in subSection.Questions)
        {
            <p>@question.QuestionText</p>
            ....
        }
    }
}

Side note: I have made the collection properties List<T> assuming that you might want to also generate a form for editing the Questions/Answers and to do so you will need a for loop which required the collection to implement IList. Alternatively you could save the extra overhead of .ToList(), keep them asIEnumerableand use a customEditorTemplate` for each view model type.

For an example of how an edit view might look (using the for loop option), refer to this answer.

Community
  • 1
  • 1