一个视图中的两个foreach循环

时间:2023-01-18 20:14:34

I have this razor view:

我有这个剃刀的观点:

@using Order.Models
@model CategoriesViewModel

@{
    ViewBag.Title = "Categories";
}
@using (Html.BeginForm())
{
    <div class="panel-group">                   
        @foreach (var p in Model.Categories)
        {
          <div class="panel panel-default">
              <div class="panel-heading">
                  <h4 class="panel-title">
                      <a data-toggle="collapse" data-parent="#accordion" href="#@p.ID.ToString()">
       @p.Name
        </a>                     
                  </h4>
              </div>
               <div id="@p.ID.ToString()" class="panel-collapse collapse">
                   <div class="panel-body">  
          @foreach (var m in p.Items)                           
                       {
                          //put items data here
                       }                      
                   </div>
    </div>
              </div>     
        }        
    </div>
}

Which uses this viewmodel:

哪个使用此viewmodel:

namespace Order.Models
{
    public class CategoriesViewModel
    {
        public IEnumerable<RestCategories> Categories;
        public List<List<RestItem>> Items;
    }
}

And the controller action is:

控制器动作是:

[HttpGet]
        public ActionResult Categories()
        {
            List<List<RestItem>> ItemsForCategory = new List<List<RestItem>>();
            API OneApi = new API();
            IEnumerable<RestCategories> itemsResult = API.GetCategoryResults("test", "test");
            if (itemsResult.Count() > 0)
            {                
                foreach (RestCategories cat in itemsResult)
                {
                    ItemsForCategory.Add(OneApi.GetItemsForCategory(ConfigurationManager.AppSettings["Key1"], ConfigurationManager.AppSettings["Key2"], cat.ID.ToString()));
                }
            }

            CategoriesViewModel modelCat = new CategoriesViewModel
            {
                Categories = itemsResult          
                .OrderBy(i=>i.Order),
                Items = ItemsForCategory                             
            };
            return View(modelCat);
        }

Now, I'm not sure if this is the right way of doing this but I want to show categories and within those categories I want to show the items in that category. I can get all the items in a list and as you can see in the view I'm trying to loop through the Items collection but I'm not able to get the Items property from the model. I also tried this approach

现在,我不确定这是否是正确的方法,但我想显示类别,在这些类别中我想显示该类别中的项目。我可以在列表中获取所有项目,正如您在视图中看到的那样,我正在尝试遍历Items集合,但是我无法从模型中获取Items属性。我也试过这种方法

@foreach (var m in Model.Items.Where(n=>n.CategoryId = p.ID))

@foreach(var.in Model.Items.Where(n => n.CategoryId = p.ID))

but still nothing.

但仍然没有。

3 个解决方案

#1


0  

Rather than have two enumerables in the model you could just have the category, and it's associated items, and then pass a list of those into the view.

您可以只使用类别中的两个枚举,而不是在关联的项目中使用两个枚举,然后将这些列表传递到视图中。

So your model would look like:

所以你的模型看起来像:

public class CategoryViewModel
{
    public RestCategories Category;
    public List<RestItem> Items;
}

Your Controller would do something like:

您的控制器会执行以下操作:

IEnumerable<RestCategories> categories = API.GetCategoryResults("test", "test");
var categoryModels = categories.OrderBy(c => c.Order)
                               .Select(c => new CategoryViewModel
                                       {
                                           Category = c,
                                           Items = OneApi.GetItemsForCategory(ConfigurationManager.AppSettings["Key1"], ConfigurationManager.AppSettings["Key2"], cat.ID.ToString())
                                       })
                               .ToList();
return View(categoryModels);

Your view would have a model type of IEnumerable<CategoryViewModel> rather than CategoriesViewModel, and would do something like this:

您的视图将具有IEnumerable 的模型类型而不是CategoriesViewModel,并且将执行以下操作:

<div class="panel-group">                   
    @foreach (var m in Model)
    {
        <div class="panel panel-default">
            <div class="panel-heading">
                <h4 class="panel-title">
                    <a data-toggle="collapse" data-parent="#accordion" href="#@m.Category.ID.ToString()">
                        @m.Category.Name
                    </a>                     
                </h4>
            </div>
            <div id="@m.Category.ID.ToString()" class="panel-collapse collapse">
                <div class="panel-body">  
                    @foreach (var i in m.Items)                           
                    {
                        //put items data here
                    }                      
                </div>
            </div>
        </div>     
    }        
</div>

#2


0  

You are trying to access a value that probably does not exist:

您正在尝试访问可能不存在的值:

@foreach (var m in Model.Items.Where(n=>n.CategoryId = p.ID))

n.CategoryId does not exist because n is referencing an item of the Items list (which is also a list).

n.CategoryId不存在,因为n引用了Items列表的项目(也是列表)。

Do you mean maybe:

你的意思是:

 @foreach (var m in Model.Items.Where(n=>n.SOMETHING = p.ID))

I write SOMETHING because you have a list of list and maybe it should be:

我写了SOMETHING,因为你有一个列表列表,也许它应该是:

public List<RestItem> Items;

and then n will have the RestItem and you would be able to access its properties.

然后n将拥有RestItem,您将能够访问其属性。

If what you need is a list for each category, then what you should have is:

如果您需要的是每个类别的列表,那么您应该拥有的是:

namespace Order.Models
{
    public class CategoriesViewModel
    {
        public IEnumerable<RestCategories> Categories;
        public List<ListRestItem> Items;
    }
    public class ListRestItem
    {
       public int CategoryId;
       public List<RestItem> Items;

    }

And with this your previous code should work. Hope it helps

有了这个,你以前的代码应该工作。希望能帮助到你

#3


0  

An alternative to my first answer would be to leave the model, and view type, as you currently have it. In the controller action you want to make sure that the two enumerables have the same ordering with respect to category. You can then combine them in the view like this:

我的第一个答案的另一种选择是离开模型和视图类型,就像你现在拥有它一样。在控制器操作中,您要确保两个枚举在类别方面具有相同的顺序。然后,您可以在视图中将它们组合在一起:

<div class="panel-group">                   
    @foreach (var m in Model.Categories.Zip(Model.Items, (c, i) => new { Category = c, Items = I }))
    {
        <div class="panel panel-default">
            <div class="panel-heading">
                <h4 class="panel-title">
                    <a data-toggle="collapse" data-parent="#accordion" href="#@m.Category.ID.ToString()">
                        @m.Category.Name
                    </a>                     
                </h4>
            </div>
            <div id="@m.Category.ID.ToString()" class="panel-collapse collapse">
                <div class="panel-body">  
                    @foreach (var i in m.Items)                           
                    {
                        //put items data here
                    }                      
                </div>
            </div>
        </div>     
    }        
</div>

#1


0  

Rather than have two enumerables in the model you could just have the category, and it's associated items, and then pass a list of those into the view.

您可以只使用类别中的两个枚举,而不是在关联的项目中使用两个枚举,然后将这些列表传递到视图中。

So your model would look like:

所以你的模型看起来像:

public class CategoryViewModel
{
    public RestCategories Category;
    public List<RestItem> Items;
}

Your Controller would do something like:

您的控制器会执行以下操作:

IEnumerable<RestCategories> categories = API.GetCategoryResults("test", "test");
var categoryModels = categories.OrderBy(c => c.Order)
                               .Select(c => new CategoryViewModel
                                       {
                                           Category = c,
                                           Items = OneApi.GetItemsForCategory(ConfigurationManager.AppSettings["Key1"], ConfigurationManager.AppSettings["Key2"], cat.ID.ToString())
                                       })
                               .ToList();
return View(categoryModels);

Your view would have a model type of IEnumerable<CategoryViewModel> rather than CategoriesViewModel, and would do something like this:

您的视图将具有IEnumerable 的模型类型而不是CategoriesViewModel,并且将执行以下操作:

<div class="panel-group">                   
    @foreach (var m in Model)
    {
        <div class="panel panel-default">
            <div class="panel-heading">
                <h4 class="panel-title">
                    <a data-toggle="collapse" data-parent="#accordion" href="#@m.Category.ID.ToString()">
                        @m.Category.Name
                    </a>                     
                </h4>
            </div>
            <div id="@m.Category.ID.ToString()" class="panel-collapse collapse">
                <div class="panel-body">  
                    @foreach (var i in m.Items)                           
                    {
                        //put items data here
                    }                      
                </div>
            </div>
        </div>     
    }        
</div>

#2


0  

You are trying to access a value that probably does not exist:

您正在尝试访问可能不存在的值:

@foreach (var m in Model.Items.Where(n=>n.CategoryId = p.ID))

n.CategoryId does not exist because n is referencing an item of the Items list (which is also a list).

n.CategoryId不存在,因为n引用了Items列表的项目(也是列表)。

Do you mean maybe:

你的意思是:

 @foreach (var m in Model.Items.Where(n=>n.SOMETHING = p.ID))

I write SOMETHING because you have a list of list and maybe it should be:

我写了SOMETHING,因为你有一个列表列表,也许它应该是:

public List<RestItem> Items;

and then n will have the RestItem and you would be able to access its properties.

然后n将拥有RestItem,您将能够访问其属性。

If what you need is a list for each category, then what you should have is:

如果您需要的是每个类别的列表,那么您应该拥有的是:

namespace Order.Models
{
    public class CategoriesViewModel
    {
        public IEnumerable<RestCategories> Categories;
        public List<ListRestItem> Items;
    }
    public class ListRestItem
    {
       public int CategoryId;
       public List<RestItem> Items;

    }

And with this your previous code should work. Hope it helps

有了这个,你以前的代码应该工作。希望能帮助到你

#3


0  

An alternative to my first answer would be to leave the model, and view type, as you currently have it. In the controller action you want to make sure that the two enumerables have the same ordering with respect to category. You can then combine them in the view like this:

我的第一个答案的另一种选择是离开模型和视图类型,就像你现在拥有它一样。在控制器操作中,您要确保两个枚举在类别方面具有相同的顺序。然后,您可以在视图中将它们组合在一起:

<div class="panel-group">                   
    @foreach (var m in Model.Categories.Zip(Model.Items, (c, i) => new { Category = c, Items = I }))
    {
        <div class="panel panel-default">
            <div class="panel-heading">
                <h4 class="panel-title">
                    <a data-toggle="collapse" data-parent="#accordion" href="#@m.Category.ID.ToString()">
                        @m.Category.Name
                    </a>                     
                </h4>
            </div>
            <div id="@m.Category.ID.ToString()" class="panel-collapse collapse">
                <div class="panel-body">  
                    @foreach (var i in m.Items)                           
                    {
                        //put items data here
                    }                      
                </div>
            </div>
        </div>     
    }        
</div>