在单个webgrid中显示多个IEnumberables和单值属性

时间:2012-10-11 16:09:51

标签: asp.net-mvc-3 webgrid

我有一个Inventory类,它不仅包含自己的字段,还包含其他类的几个引用ID。

public class Inventory {

  public int Id { get; set; }

  public string RtNum { get; set; }

  public string AcntNum { get; set; }

  public string CardNum { get; set; }

  public string Num { get; set; }

  [Range(1,3)]
  public int Type { get; set; }

  public int CompanyId { get; set; }

  public int BranchId { get; set; }

  public int PersonId { get; set; }   }

在我的操作中,我从其他类生成了几个相关字段的IEnumerable列表。我还有几个非列表值要传递给View。我知道如何创建一个ViewModel来将所有内容传递给webgrid但无法遍历列表。我也知道如何将索引自动映射到一个列表,请参阅How to display row number in MVC WebGrid。 你如何将两者结合起来,以便可以使用索引迭代多个列表?

更新#1(更多细节)

public class Company {
  public int Id { get; set; } 
  public string Name { get; set; }   }

public class Branch {
  public int Id { get; set; } 
  public string Name { get; set; }   }

public class Person  {
  public int Id { get; set; } 
  public string Name { get; set; }   }

public class MyViewModel  {
  public int PageNumber { get; set; }
  public int TotalRows { get; set; }
  public int PageSize { get; set; }
  public IEnumerable<Inventory> Inventories { get; set; }
  public int Index { get; set; }
  public IEnumerable<string> CmpNm { get; set; }
  public IEnumerable<string> BrnNm { get; set; }
  public IEnumerable<string> PrnNm { get; set; }        }

控制器

public class InventoryController : Controller
{  // I have a paged gird who’s code is not relevant to this discussion but a pagenumber,
   //  pagesize and totalrows will be generated
   private ProjectContext _db = new ProjectContext();

   public ActionResult Index()  {
     IEnumerable<Inventory> inventories = _db.Inventories;
     List<string> cmpNm = new List<string>; List<string> brnNm = new List<string>; List<string>     prnNm = new List<string>;
     foreach (var item in inventories) { string x1 = ""; 
     Company cmps = _db. Company.SingleOrDefault(i => i.Id == item.CompanyId); if (cmps!= null)
      { x1 = cmps.Name; } cmpNm.Add(x1); x1 = "";
     Branch brns = _db. Branch.SingleOrDefault(i => i.Id == item. Branch Id); if (brns!= null) { x1 = brns.Name; } brnNm.Add(x1); x1 = "";
     Person pers = _db.Persons.SingleOrDefault(i => i.Id == item. PersonId);
      if (pers!= null) { x1 = pers.Name; } prnNm.Add(x1); 

     // the MyViewModel now needs to populated with all its properties and generate an index
     // something along the line of 
     new MyViewModel { PageNumber= pagenumber, PageSize= pagesize,  TotalRows=Totalrows, Inventories = inventories;  CmpNm=cmpNm, BrnNm=brnNm, PrnNm=prnNm}

查看(如何创建索引是问题)

@model.Project.ViewModels.MyViewModel
@{ var grid = new WebGrid(Model.Inventories, Model.TotalRows, rowsPerPage: Model.PageSize); }
@grid.GetHtml( columns: grid.Columns( 
    Grid.Column(“PrnNm”, header: "Person", format: @Model.PrnNm.ElementAt(Index))
    Grid.Column(“BrnNm”, header: "Branch", format: @Model.BrnNm.ElementAt(Index))
    Grid.Column(“CmpNm”, header: "Company", format: @Model.CmpNm.ElementAt(Index))
    grid.Column("RtNum", header: "Route"), 
    grid.Column("AcntNum", header: "Account"), 
    grid.Column("CardNum", header: "Card")
    …      )    )

网格应该是什么样子是不言而喻的。

1 个答案:

答案 0 :(得分:2)

目前还不清楚你的目标是什么。但无论它是什么,我建议你定义一个真实的视图模型,反映你的视图的要求,只包含你有兴趣在这个网格中看到的信息:

public class InventoryViewModel
{
    public int Id { get; set; }
    public string PersonName { get; set; }
    public string BranchName { get; set; }
    public string CompanyName { get; set; }
    public string RouteNumber { get; set; }
    public string AccountNumber { get; set; }
    public string CardNumber { get; set; }
}

现在您可以拥有主视图模型:

public class MyViewModel
{
    public int PageNumber { get; set; }
    public int TotalRows { get; set; }
    public IEnumerable<InventoryViewModel> Inventories { get; set; }
}

好的,现在看来很明显:

@model MyViewModel

@{ 
    var grid = new WebGrid(
        Model.Inventories, 
        rowsPerPage: Model.PageSize
    ); 
}

@grid.GetHtml( 
    columns: grid.Columns( 
        grid.Column("Id", header: "Inventory id"),
        grid.Column("PersonName", header: "Person"),
        grid.Column("BranchName", header: "Branch"),
        grid.Column("CompanyName", header: "Company"),
        grid.Column("RouteNumber", header: "Route"), 
        grid.Column("AccountNumber", header: "Account"), 
        grid.Column("CardNumber", header: "Card")
    )    
)

现在剩下的就是在你的控制器中构建这个视图模型。由于我不知道你想要在这里实现什么,无论你需要在这些列上使用内连接还是左外连接,我将以左外连接为例:

public ActionResult Index()
{
    var inventories = 
        from inventory in _db.Inventories
        join person in _db.Persons on inventory.PersonId equals person.Id into outerPerson
        join company in _db.Companies on inventory.CompanyId equals company.Id into outerCompany
        join branch in _db.Branch on inventory.BranchId equals branch.Id into outerBranch
        from p in outerPerson.DefaultIfEmpty()
        from c in outerCompany.DefaultIfEmpty()
        from b in outerBranch.DefaultIfEmpty()
        select new InventoryViewModel
        { 
            PersonName = (p == null) ? string.Empty : p.Name,
            CompanyName = (c == null) ? string.Empty : c.Name,
            BranchName = (b == null) ? string.Empty : b.Name,
            Id = inventory.Id,
            AccountNumber = inventory.AcntNum,
            CardNumber = inventory.CardNum,
            RouteNumber = inventory.RtNum
        };


    var model = new MyViewModel
    {
        PageSize = 5,
        // TODO: paging
        Inventories = inventories.ToList()
    };

    return View(model);
}

这就是它。当然,在这个例子中,我将为您保留Inventories系列的分页。现在.Skip().Take()所需的记录数量应该非常简单。

正如您所看到的,ASP.NET MVC非常简单。您可以定义视图模型以反映需要在视图中显示的内容的确切要求,然后在控制器中填充此视图模型。大多数人都避免使用视图模型,因为他们无法填充它们,可能是因为他们缺乏对所使用的底层数据访问技术的了解。正如您在本示例中所看到的,困难并不在于ASP.NET MVC。它位于LINQ查询中。但LINQ严格与MVC无关。除了MVC之外,还应该学习它。当你做MVC时,总是要考虑视图模型以及需要向用户呈现的信息。不要考虑数据库中的内容或信息的来源。