0

I have a Razor view that iterates over a collection property on the view model, and a display template for a single item on that collection. In that single item, I then do the same thing again, so that under the hood I have nested loops that render instances of the same type a number of times on the page.

In the display template for the leaf type, I'd like to find out how many similar items have already been rendered to the page.

I tried to add a property to the ViewBag and increment it on each iteration, but that didn't work.

Model

public class FooViewModel
{
    public IEnumerable<Bar> Bars { get; set; }
}
public class BarViewModel
{
    public IEnumerable<Baz> Bazes { get; set; } // how do you pluralize baz?
}
public class BazViewModel
{
}

Index.cshtml

@model FooViewModel

@{
    ViewBag.RenderCount = 0;
}
@Html.DisplayFor(m => m.Bars);

DisplayTemplates/BarViewModel.cshtml

@model BarViewModel
@Html.DisplayFor(m => m.Bazes);

DisplayTemplates/BazViewModel.cshtml

@model BazViewModel

// how many BazViewModels have been rendered before this one?
@ViewBag.RenderCount // is 0 every time

@{
    ViewBag.RenderCount++;
}
Tomas Aschan
  • 58,548
  • 56
  • 243
  • 402
  • 1
    I'm not really following your question but all processing should be done inside the controller. Try and avoid putting logic in the views at all. It looks like you need a viewmodel with an incrementing counter. Each view will have it's own instance of Viewbag so you can't use this as a global variable (which is what I think your trying to do). – Liam Aug 09 '17 at 14:35
  • 1
    So do all your processing in the controller, then just give your views the data to render, then you don't need to share data at all – Liam Aug 09 '17 at 14:38
  • @Liam Thanks; that's probably a better way to solve this problem. – Tomas Aschan Aug 09 '17 at 15:19
  • Just noticed for myself, that there is overload version `DisplayFor(HtmlHelper, Expression>, Object)` And [here](https://stackoverflow.com/questions/4865162/asp-mvc-partial-with-model-and-viewdatadictionary-how-do-i-access-the-viewdata) is example of usage. – Vitaliy Smolyakov Aug 09 '17 at 15:32
  • You can just use `int num = model.Bars.SelectMany(x => x.Bazes).Count();` in the controller to get the total, but if you want to show incremented values in the view code, then you will need nested `for` loops –  Aug 09 '17 at 23:53

1 Answers1

0

As suggested by Liam in the comments, I ended up moving this processing into the Controller (or, actually, into the mapping from my data entities into view models). This entailed adding a property to the view model where I needed the count, and setting that property as part of the mapping process.

Tomas Aschan
  • 58,548
  • 56
  • 243
  • 402