在cshtml中分组

Posted

技术标签:

【中文标题】在cshtml中分组【英文标题】:GroupBy in cshtml 【发布时间】:2021-12-25 20:44:19 【问题描述】:

我正在尝试按表中的 PlayerId 进行分组,但出现以下错误:

'IGrouping' 不包含 'Player' 的定义,并且找不到可访问的扩展方法 'Player' 接受类型为 'IGrouping' 的第一个参数(您是否缺少使用指令还是程序集引用?)

任何帮助将不胜感激。

查看

@model IEnumerable<Block_City_Website.Models.Stat>
@using static MoreLinq.Extensions.LagExtension;
@using static MoreLinq.Extensions.LeadExtension;
@using MoreEnumerable = MoreLinq.MoreEnumerable;

<div class="container p-3">
    <div class="row pt-4">
        <div class="col-6">
            <h2 class="text-primary">Stats List</h2>
        </div>
        <div class="col-6 text-right">
            <a asp-controller="Stat" asp-action="Index" class="btn btn-primary">Back to Stats</a>
        </div>
    </div>
    <br />

    @if (Model.Count() > 0)
    


        <table class="table table-bordered table-striped" style="width:100%">
            <thead>
                <tr>
                    <th>
                        Player
                    </th>
                    <th>
                        Team
                    </th>
                    <th>
                        Points
                    </th>
                    <th>
                        Rebounds
                    </th>
                    <th>
                        Assists
                    </th>
                    <th>
                        Steals
                    </th>
                    <th>
                        Blocks
                    </th>
                </tr>
            </thead>
            <tbody>

                           

                @foreach (var stat in Model.GroupBy(x => x.PlayerId))
                
                    <tr>
                        <td >@stat.Player.FirstName @stat.Player.LastName</td>
                        <td >@stat.Team.TeamName</td>
                        <td >@stat.Points</td>
                        <td >@stat.Rebounds</td>
                        <td >@stat.Assists</td>
                        <td >@stat.Steals</td>
                        <td >@stat.Blocks</td>
                    </tr>

                
            </tbody>
        </table>
    
    else
    
        <p>No Stats created yet</p>
    
</div>
@if (Model.Count() > 0)



    <table class="table table-bordered table-striped" style="width:100%">
        <thead>
            <tr>
                <th>
                    Player
                </th>
                <th>
                    Team
                </th>
                <th>
                    Points
                </th>
                <th>
                    Rebounds
                </th>
                <th>
                    Assists
                </th>
                <th>
                    Steals
                </th>
                <th>
                    Blocks
                </th>
            </tr>
        </thead>
        <tbody>

            <tr>
                <td >Stephen Curry</td>
                <td >Warriors</td>
                <td >58</td>
                <td >15</td>
                <td >12</td>
                <td >5</td>
                <td >3</td>
            </tr>
            <tr>
                <td >Lebron James</td>
                <td >Lakers</td>
                <td >64</td>
                <td >19</td>
                <td >17</td>
                <td >5</td>
                <td >5</td>
            </tr>


        </tbody>
    </table>

else

    <p>No Stats created yet</p>

<div>

</div>

控制器

using Block_City_Website.Data;
using Block_City_Website.Models;
using Block_City_Website.Models.ViewModels;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Block_City_Website.Controllers

    public class StatController : Controller
    
        private readonly ApplicationDbContext _db;

        public StatController(ApplicationDbContext db)
        
            _db = db;
        

        
            public IActionResult Index()
        



            IEnumerable<Stat> objList = _db.Stats;

            foreach(var obj in objList)
            
                obj.Player = _db.Players.FirstOrDefault(u => u.Id == obj.PlayerId);
                obj.Team = _db.Teams.FirstOrDefault(u => u.Id == obj.TeamId);


            

            return View(objList);
        


        //GET-Create
        public IActionResult Create()
        
            //IEnumerable<SelectListItem> TypeDropDown = _db.Players.Select(i => new SelectListItem
            //
            //    Text = i.FirstName + " " +i.LastName,
            //    Value = i.Id.ToString()
            //);

            //ViewBag.TypeDropDown = TypeDropDown;

            StatVM statVM = new StatVM()
            
                Stat = new Stat(),
                TypeDropDown = _db.Players.Select(i => new SelectListItem
                
                    Text = i.FirstName + " " + i.LastName,
                    Value = i.Id.ToString()
                ),
                TypeDropDown1 = _db.Teams.Select(i => new SelectListItem
                
                    Text = i.TeamName,
                    Value = i.Id.ToString()
                )
            ;

            return View(statVM);
        

        //POST-Create
        [HttpPost]
        [ValidateAntiForgeryToken]
        public IActionResult Create(StatVM obj)
        
            if (ModelState.IsValid)
            
                //obj.PlayerId = 1;
                //obj.TeamId = 1; 
                _db.Stats.Add(obj.Stat);
                _db.SaveChanges();
                return RedirectToAction("Index");

            
            return View(obj);
        

        // GET-Delete
        public IActionResult Delete(int? id)
        
            if (id == null || id == 0)
            
                return NotFound();
            
            var obj = _db.Stats.Find(id);
            if (obj == null)
            
                return NotFound();
            
            return View(obj);
        

        // POST-Delete
        [HttpPost]
        [ValidateAntiForgeryToken]
        public IActionResult DeletePost(int? id)
        
            var obj = _db.Stats.Find(id);
            if (obj == null)
            
                return NotFound();
            
            _db.Stats.Remove(obj);
            _db.SaveChanges();
            return RedirectToAction("Index");
        

        // GET Update
        public IActionResult Update(int? id)
        
            StatVM expenseVM = new StatVM()
            
                Stat = new Stat(),
                TypeDropDown = _db.Players.Select(i => new SelectListItem
                
                    Text = i.FirstName + " " + i.LastName,
                    Value = i.Id.ToString()
                ),
                TypeDropDown1 = _db.Teams.Select(i => new SelectListItem
                
                    Text = i.TeamName,
                    Value = i.Id.ToString()
                )
            ;

            if (id == null || id == 0)
            
                return NotFound();
            
            expenseVM.Stat = _db.Stats.Find(id);
            if (expenseVM.Stat == null)
            
                return NotFound();
            
            return View(expenseVM);

        

        // POST UPDATE
        [HttpPost]
        [ValidateAntiForgeryToken]
        public IActionResult Update(StatVM obj)
        
            if (ModelState.IsValid)
            
                _db.Stats.Update(obj.Stat);
                _db.SaveChanges();
                return RedirectToAction("Index");
            
            return View(obj);

        

        public IActionResult TotStats()
        



            IEnumerable<Stat> objList = _db.Stats;

            foreach (var obj in objList)
            
                obj.Player = _db.Players.FirstOrDefault(u => u.Id == obj.PlayerId);
                obj.Team = _db.Teams.FirstOrDefault(u => u.Id == obj.TeamId);
            

            return View(objList);
        


    

型号

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Threading.Tasks;

namespace Block_City_Website.Models

    public class Stat
    
        [Key]
        public int Id  get; set; 

        [Required]
        [Range(0, int.MaxValue, ErrorMessage ="Amount must not be less than 0")]
        public int Points  get; set; 

        [Required]
        [Range(0, int.MaxValue, ErrorMessage = "Amount must not be less than 0")]
        public int Rebounds  get; set; 

        [Required]
        [Range(0, int.MaxValue, ErrorMessage = "Amount must not be less than 0")]
        public int Assists  get; set; 

        [Required]
        [Range(0, int.MaxValue, ErrorMessage = "Amount must not be less than 0")]
        public int Steals  get; set; 

        [Required]
        [Range(0, int.MaxValue, ErrorMessage = "Amount must not be less than 0")]
        public int Blocks  get; set; 

        [Required]
        [DisplayName("Player")]
        public int PlayerId  get; set; 
        [ForeignKey("PlayerId")]
        public virtual Player Player  get; set; 

        [Required]
        [DisplayName("Team")]
        public int TeamId  get; set; 
        [ForeignKey("TeamId")]
        public virtual Team Team  get; set; 
    


【问题讨论】:

【参考方案1】:

当您运行一个组时,它会将一个平面对象列表转换为一个列表列表。像这样的平面列表:

PlayerScore 
.PlayerId, .GameScore
1, 20
1, 40 
1, 60
2, 30
2, 50

按 PlayerId 分组,最终看起来像这样:

Key, (list of PlayerScores)
1, [1,20, 1,40, 1,60]
2, [2,30, 2,50]

所以你需要欣赏的是你的 GroupBy 已经产生了一个列表列表,你不能再直接输出玩家的东西了;你foreaching 的每个stat 条目本身就是一个统计对象的集合

这意味着你必须做一些在列表上下文中有意义的事情

            foreach (var stats in Model.GroupBy(x => x.PlayerId))
            
                <tr>
                    <td >@stats.First().Player.FirstName @stats.First().Player.LastName</td>
                    <td >@stats.First().Team.TeamName</td>
                    <td >@stats.Sum(stat => stat.Points)</td>
                    <td >@stats.Sum(stat => stat.Rebounds)</td>
                    <td >@stats.Sum(stat => stat.Assists)</td>
                    <td >@stats.Sum(stat => stat.Steals)</td>
                    <td >@stats.Sum(stat => stat.Blocks)</td>

我将stat 重命名为stats 以概述您正在使用foreaching 的项目中可能有多个内容,我假设您希望对数字统计数据进行总结,但如果您有其他想法,例如平均你必须改变它

【讨论】:

以上是关于在cshtml中分组的主要内容,如果未能解决你的问题,请参考以下文章

在图像标签中使用 cshtml?

从 Layout.cshtml 调用方法

模型不会从剃刀页面中的 _Layout.cshtml 页面中的 _Footer.cshtml 部分视图绑定

无法在 cshtml 中加载 ReportViewerForMvc 参考

视图(.cshtml)文件中的编译错误

Asp.Net Core 入门—— 布局视图_Layout.cshtml