如何转换List <ienumerable <productviewmodel>&gt;进入<ienumerable <productviewmodel>&gt;?

时间:2017-01-09 16:27:52

标签: c# asp.net-mvc linq

我正在访问类别ICollection<Product> Products属性中的数据。如果您查看下面的控制器代码,使用第二个选择,我将每个产品的Form从Product实体更改为ProductViewModel,它返回IQueryable<IEnumerable<ProductViewModel>>

最后,使用ToListAsync()方法,模型返回List<IEnumerable<ProductViewModel>>View不接受该var model = (await db.Categories.Where(c => c.Id == id).Select(p => p.Products.Select(x => new ProductViewModel { Id = x.Id, Name = x.Name, ByteImage = x.Image, Price = x.Price})).ToListAsync()); return View(model);

我的控制器模型是:

List<IEnumerable<ProductViewModel>>

此模型的返回类型为View,我无法在View中迭代此模型以显示数据。

查看给@model IEnumerable<ProductViewModel>的模型是:

Source Error: Line 14: <tr> Line 15: <th> Line 16: @Html.DisplayNameFor(model => model.Name) Line 17: Line 18: </th>

这是我收到的错误消息:

  

编译器错误消息:CS0411:无法从用法推断出方法'DisplayNameExtensions.DisplayNameFor(HtmlHelper,Expression&gt;)'的类型参数。尝试明确指定类型参数。

public class ProductViewModel
    {
        public int Id { get; set; }
        [Required, Display(Name="Product Name")]
        public string Name { get; set; }
        [Required, DataType(DataType.Upload)]
        public HttpPostedFileBase Image { get; set; }
        public string OutputImage { get; set; }
        public Byte[] ByteImage { get; set; }
        [Required]
        public Decimal Price { get; set; }

        public static byte[] ConvertToByte(ProductViewModel model)
        {
            if (model.Image != null)
            {
                byte[] imageByte = null;
                BinaryReader rdr = new BinaryReader(model.Image.InputStream);
                imageByte = rdr.ReadBytes((int)model.Image.ContentLength);

                return imageByte;
            }

            return null;
        }

        // ViewModel => Model | Implicit type Operator
        public static implicit operator Product(ProductViewModel viewModel)
        {
            var model = new Product
            {
                Id = viewModel.Id,
                Name = viewModel.Name,
                Image = ConvertToByte(viewModel),
                Price = viewModel.Price
            };

            return model;
        }

        // Model => ViewModel | Implicit type Operator
        public static implicit operator ProductViewModel(Product model)
        {
            var viewModel = new ProductViewModel
            {
                Id = model.Id,
                Name = model.Name,
                OutputImage = string.Format("data:image/jpg;base64,{0}", Convert.ToBase64String(model.Image)),
                Price = model.Price
            };

            return viewModel;
        }

    }

ProductViewModel:

@model List<ValueVille.Models.ProductViewModel>
@using MvcApplication8.Models

@{
    ViewBag.Title = "Index";
}

<h2>Index</h2>

<p>
    @Html.ActionLink("Create New", "Create")
</p>
<table class="table">
    <tr>
        <th>
            @Html.DisplayNameFor(model => model.Name)

        </th>
        <th>
            @Html.DisplayNameFor(model => model.Image)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.Price)
        </th>
        <th></th>
    </tr>

@foreach (var item in Model) {
    <tr>
        <td>
            @Html.DisplayFor(modelItem => item.Name)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.Image)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.Price)
        </td>
        <td>
            @Html.ActionLink("Edit", "Edit", new { id=item.Id }) |
            @Html.ActionLink("Details", "Details", new { id=item.Id }) |
            @Html.ActionLink("Delete", "Delete", new { id=item.Id })
        </td>
    </tr>
}

</table>

这是查看索引:

Sub NormalizeRange(R As Range)
    'assumes that R is a rectangular range
    'will throw an error if any column has max 0

    Dim vals As Variant, maxes As Variant
    Dim i As Long, j As Long, m As Long, n As Long

    m = R.Rows.Count
    n = R.Columns.Count
    ReDim maxes(1 To n)

    With Application.WorksheetFunction
        For i = 1 To n
            maxes(i) = .Max(R.Columns(i))
        Next i
    End With

    vals = R.Value
    For i = 1 To m
        For j = 1 To n
            vals(i, j) = vals(i, j) / maxes(j)
        Next j
    Next i
    R.Value = vals
End Sub

2 个答案:

答案 0 :(得分:7)

您需要使用SelectMany代替:

(await db.Categories
         .Where(c => c.Id == id)
         .SelectMany(p => p.Products.Select(x => new ProductViewModel { Id = x.Id, Name = x.Name, ByteImage = x.Image, Price = x.Price }))
         .ToListAsync());
当您想要将多个序列投影到单个(平面)序列中时,

SelectMany非常有用。

根据您的更新:

由于您的模型实际上是List<ProductViewModel>,因此当您想要显示某个属性的名称时,您需要指向列表中的实际ProductViewModel实例。 / p>

例如:

@Html.DisplayNameFor(model => model[0].Name)

请参阅MSDN

答案 1 :(得分:1)

目前,您的序列看起来像这样

[ [model1, model2, model3], [model4, model] ]

将你弄平可以

model.SelectMany(m => m)

[ model1, model2, model3, model4, model5 ]

(如果那真的是你想要的那样)