从多个字段填充ViewModel集合

时间:2017-09-25 11:05:44

标签: c# asp.net asp.net-mvc

我有一个表单,用户可以在其中选择他们想要为他们销售的产品支持的运输方式,例如一等信,二等信,包裹等。我只向用户提供一系列可能的运输方式,他们宣布每个人的费用是多少,所以如果有人想在一个包裹里卖烤面包机,他们的收费会低于一套哑铃。

我的ProductViewModel

public int Id { get; set; }

public ICollection<SelectedShippingMethodViewModel> SelectedShippingMethods { get; set; }

SelectedShippingMethodViewModel

public class SelectedShippingMethodViewModel
{
    public string Name { get; set; }
    public decimal Price { get; set; }
}

在我的表单中,我创建了一个包含可能选项的部分:

<h3>Add new product</h3>
<hr />
@using (Html.BeginForm("AddNew", "ProductCreator", null, FormMethod.Post, new { @class = "form-horizontal", role = "form" }))
{
    @Html.AntiForgeryToken()

    <div class="form-group">
        <label class="col-sm-2 control-label">Shipping methods</label>
        <div class="col-sm-10">
            @foreach (ShippingMethod shippingMethod in ViewBag?.ShippingMethods)
            {
                <div class="row">
                    <div class="col-md-3">
                        // I don't know what should be here
                        @Html.CheckBox("SelectedShippingMethods", false)
                        @shippingMethod.Name
                    </div>
                    <div class="col-md-2">
                        // I don't know what should be here
                        @Html.TextBox("SelectedShippingMethods.Price")
                    </div>
                </div>
            }
        </div>
    </div>
    <div class="form-group">
        <div class="col-sm-offset-2 col-sm-10">
            <button type="submit" class="btn btn-default">Add product</button>
        </div>
    </div>
}

我有一个数据库表,其中包含我获得的每种可能的送货方式:

[HttpGet]
public async Task<ActionResult> AddNew()
{
    ViewBag.ShippingMethods = await _shippingService.GetAllShippingMethodsAsync();
    return View();
}

问题是如果选中了复选框,我必须为每个Price绑定NameSelectedShippingMethodViewModel,我不知道如何使其工作。

1 个答案:

答案 0 :(得分:1)

您的视图模型不正确。要允许用户选择他们想要的运输方式并添加价格,该视图模型需要

public class ShippingMethodViewModel
{
    public string Name { get; set; }
    public decimal Price { get; set; }
    public bool IsSelected { get; set; } // your checkbox binds to this property
}

并且ProductViewModel应为

public class ProductViewModel
{
    public int Id { get; set; }
    ....
    public List<ShippingMethodViewModel> ShippingMethods { get; set; }
}

然后在GET方法中,初始化您的ProductViewModel并根据所有可用的ShippingMethods填充ShippingMethods,例如

var shippingMethods = await _shippingService.GetAllShippingMethodsAsync()
ProductViewModel model = new ProductViewModel
{
    ....
    ShippingMethods = shippingMethods.Select(x => new ShippingMethodViewModel
    {
        Name = x.Name
    }).ToList()
};
return View(model);

并在视图中,使用for循环或EditorTemplate类型ShippingMethodViewModel来正确生成表单控件

@for (int i = 0; i < Model.ShippingMethods.Count; i++)
{
    @Html.LabelFor(m => m.ShippingMethods[i].IsSelected, Model[0].ShippingMethods.Name)  
    @Html.CheckBoxFor(m => m.ShippingMethods[i].IsSelected)

    @Html.LabelFor(m => m.ShippingMethods[i].Price)       
    @Html.TextBoxFor(m => m.ShippingMethods[i].Price)

    @Html.HiddenFor(m => m.ShippingMethods[i].Name) // if you want this to be submitted as well
}

然后在POST方法中

public ActionResult AddNew(ProductViewModel model)
{
     // Get the selected Shipping Methods and the associated price
     var selectedMethods = model.ShippingMethods.Where(x => x.Selected);