显示对象列表,并为每个输入MVC设置一个值字段

本文关键字:设置 字段 一个 MVC 输入 列表 对象 显示 | 更新日期: 2023-09-27 17:54:51

我有以下类定义为我的ViewModel

 public class CreateApplicationViewModel
    {
        public Step1ViewModel Step1 { get; set; }
        public Step2StandAloneViewModel Step2StandAlone { get; set; }
        public Step2ChildViewModel Step2Child { get; set; }
        public Step3ViewModel Step3 { get; set; }
        public Step4ViewModel Step4 { get; set; }
    }

我试图在包含以下内容的Step4ViewModel中显示项目:

 public class Step4ViewModel
    {
        public List<DataDetails> DataDetails = new List<DataDetails>();
    }
public class DataDetails
    {
        public string GroupCode { get; set; }
        public string GroupDesc { get; set; }
        public decimal DetailSequence { get; set; }
        public string DetailCode { get; set; }
        public string DetailDesc { get; set; }
        public string YesNoFlag { get; set; }
        public string NumberFlag { get; set; }
        public string ValueFlag { get; set; }
        public string DateFlag { get; set; }
        public string ListValuesFlag { get; set; }
        public string CommentFlag { get; set; }
        public string CalcRateFlag { get; set; }
        public string ColumnSequence { get; set; }
        public string TextFlag { get; set; }
        public string CheckboxFlag { get; set; }
        public string YesNoValue { get; set; }
        public int NumberValue { get; set; }
        public DateTime DateValue { get; set; }
        public string ListValue { get; set; }
        public string CommentValue { get; set; }
        public string TextValue { get; set; }
        public bool CheckboxValue { get; set; }
    }
在我的控制器中,我填充了Step4ViewModel。数据详情如下:
private Step4ViewModel GetCaseDataDetails(string caseType)
        {
            Step4ViewModel model = new Step4ViewModel();
            List<DataDetails> data = new List<DataDetails>();
            List<DataDetailsValues> values = new List<DataDetailsValues>();
            var dataDetails = (from tb1 in db.DEFAULT_CASE_DATA_VW
                               join tb2 in db.CASE_DATA_DETAIL on tb1.CASE_DATA_GROUP_ID equals tb2.CASE_DATA_GROUP_ID
                               where tb1.BUS_CASE_CODE == caseType
                               orderby tb2.DETAIL_SEQUENCE
                               select new { tb1, tb2 });

            foreach (var detail in dataDetails.ToList())
            {
                DataDetails i = new DataDetails();
                DataDetailsValues j = new DataDetailsValues();
                i.CalcRateFlag = detail.tb2.CALC_RATE_FLAG;
                i.CheckboxFlag = detail.tb2.CHECKBOX_FLAG;
                i.ColumnSequence = detail.tb2.COLUMN_SEQUENCE;
                i.CommentFlag = detail.tb2.COMMENT_FLAG;
                i.DateFlag = detail.tb2.DATE_FLAG;
                i.DetailCode = detail.tb2.DETAIL_CODE;
                i.DetailDesc = detail.tb2.DETAIL_DESC;
                i.DetailSequence = detail.tb2.DETAIL_SEQUENCE;
                i.GroupCode = detail.tb1.GROUP_CODE;
                i.GroupDesc = detail.tb1.GROUP_DESC;
                i.ListValuesFlag = detail.tb2.LIST_VALUES_FLAG;
                i.NumberFlag = detail.tb2.NUMBER_FLAG;
                i.TextFlag = detail.tb2.TEXT_FLAG;
                i.ValueFlag = detail.tb2.VALUE_FLAG;
                i.YesNoFlag = detail.tb2.YES_NO_FLAG;
                data.Add(i);
            }
            model.DataDetails = data;
            return model;
        }

我对Step4ViewModel的思考过程是,对于每个DataDetail,我将显示DetailDesc作为标签,然后在它旁边,我将根据控件类型为NumberValue, YesOrNoValue, NumberValue, DateValue, ListValue, CommentValue, TextValue或CheckboxValue输入,然后将该数据发布到服务器。我能够成功地显示每个DataDetail。但是对于每个输入(也会呈现),我在输入中输入的值永远不会发送回服务器。下面是我的视图:

@model Portal.Models.ViewModel.CreateApplicationViewModel
@{
    ViewBag.Title = "Step 4/5";
    Layout = "~/Views/Shared/_Layout.cshtml";
}
@using System.Linq
<h4>Case Data Details</h4>
@using (Html.BeginForm("Step4", "CreateApplication", FormMethod.Post, new { @class = "col-sm-12" }))
{
    foreach (var group in Model.Step4.DataDetails.GroupBy(item => item.GroupDesc))
    {
        <div class="panel panel-primary">
            <div class="panel-heading">@Html.Encode(group.Key)</div>
            <div class="panel-body">
                @for (var i = 0; i < group.Count(); i++)
                { 
                    <div class="form-group">
                        <div class="row">
                            <div class="col-xs-6">
                                <label class="form-label">@Model.Step4.DataDetails[i].DetailDesc</label>
                            </div>
                            <div class="col-xs-6">
                                @if (Model.Step4.DataDetails[i].TextFlag == "Y")
                                {
                                    @Html.TextBoxFor(val => Model.Step4.DataDetails[i].TextValue, new { @class = "form-control" })
                                }
                                else if (Model.Step4.DataDetails[i].CheckboxFlag == "Y")
                                {
                                    @Html.CheckBoxFor(val => Model.Step4.DataDetails[i].CheckboxValue, new { @class = "checkbox" })
                                }
                            </div>
                        </div>
                    </div>
                }
            </div>
        </div>
    }
    <div class="col-sm-12">
        <div class="row">
            @Html.ActionLink("Cancel", "Welcome", "Home", null, new { @class = "btn btn-default" })
            <button class="btn btn-default" onclick="history.go(-1);">Previous</button>
            <button type="submit" class="btn btn-default">Next</button>
        </div>
    </div>

发送数据到的控制器

[HttpPost] 
public ActionResult Step4(Step4ViewModel step4) 
{ 
    if (ModelState.IsValid) 
    { 
        CreateApplicationViewModel model = (CreateApplicationViewModel)Session["case"]; 
        // model.Step4 = step4; 
        Session["case"] = model; 
        return View(); 
    } 
    return View(); 
}

我认为这可能是由于分组,我这样做是为了将每个组分开到一个单独的HTML面板元素,但我的输入是用名称中的索引号呈现的。任何帮助或建议,一个更好的方式来实现这一点,将不胜感激。干杯!

这是我更新后的post控制器和视图:

@model Portal.Models.ViewModel.CreateApplicationViewModel
@{
    ViewBag.Title = "Step 4/5";
    Layout = "~/Views/Shared/_Layout.cshtml";
}
@using System.Linq
<h4>Case Data Details</h4>
@using (Html.BeginForm("Step4", "CreateApplication", FormMethod.Post, new { @class = "col-sm-12" }))
{
    int index = 0;
    foreach (var group in Model.Step4.DataDetails.GroupBy(item => item.GroupDesc))
    {
        <div class="panel panel-primary">
            <div class="panel-heading">@Html.Encode(group.Key)</div>
            <div class="panel-body">
                <input type="hidden" name="Step4.DataDetails.Index" value="@index" />
                @for (var i = 0; i < group.Count(); i++)
                {
                    <div class="form-group">
                        <div class="row">
                            <div class="col-xs-6">
                                <label class="form-label">@Model.Step4.DataDetails[i].DetailDesc</label>
                            </div>
                            <div class="col-xs-6">
                                @if (Model.Step4.DataDetails[i].TextFlag == "Y")
                                {
                                    @Html.TextBoxFor(val => val.Step4.DataDetails[i].TextValue, new { @class = "form-control" })
                                }
                                else if (Model.Step4.DataDetails[i].CheckboxFlag == "Y")
                                {
                                    @Html.CheckBoxFor(val => val.Step4.DataDetails[i].CheckboxValue, new { @class = "checkbox" })
                                }
                            </div>
                        </div>
                    </div>
                }
            </div>
        </div>
        index++;
    }
    <div class="col-sm-12">
        <div class="row">
            @Html.ActionLink("Cancel", "Welcome", "Home", null, new { @class = "btn btn-default" })
            <button class="btn btn-default" onclick="history.go(-1);">Previous</button>
            <button type="submit" class="btn btn-default">Next</button>
        </div>
    </div>
}

[HttpPost]
        public ActionResult Step4(CreateApplicationViewModel step4)
        {
            if (ModelState.IsValid)
            {
                CreateApplicationViewModel model = (CreateApplicationViewModel)Session["case"];
               // model.Step4 = step4;
                Session["case"] = model;
                return View();
            }
            return View();
        }

更新2

我能够得到表单输入,如果我传递一个FormCollection到HttpPost控制器。任何想法,为什么我可以得到这些值作为一个FormCollection,而不是作为模型?

显示对象列表,并为每个输入MVC设置一个值字段

您正在张贴复杂对象列表。但是MVC DefaultModelBinder不能绑定到你的DataDetails对象,因为索引必须在序列时张贴表单与复杂对象的列表。在您的情况下,由于嵌套的for循环,该序列被打破。所以你能做的就是拿一个单独的变量,用默认的0值初始化,就像这样——我试着修改你的代码。

@using (Html.BeginForm("Step4", "CreateApplication", FormMethod.Post, new { @class = "col-sm-12" }))
{
    int index = 0;
    foreach (var group in Model.Step4.DataDetails.GroupBy(item => item.GroupDesc))
    {
        <div class="panel panel-primary">
            <div class="panel-heading">@Html.Encode(group.Key)</div>
            <div class="panel-body">
                <input type="hidden" name="Step4.DataDetails.Index" value="@index" />
                @for (var i = 0; i < group.Count(); i++)
                { 
                    <div class="form-group">
                        <div class="row">
                            <div class="col-xs-6">
                                <label class="form-label">@Model.Step4.DataDetails[i].DetailDesc</label>
                            </div>
                            <div class="col-xs-6">
                                @if (Model.Step4.DataDetails[i].TextFlag == "Y")
                                {
                                    @Html.TextBoxFor(val => val.Step4.DataDetails[i].TextValue, new { @class = "form-control" })
                                }
                                else if (Model.Step4.DataDetails[i].CheckboxFlag == "Y")
                                {
                                    @Html.CheckBoxFor(val => val.Step4.DataDetails[i].CheckboxValue, new { @class = "checkbox" })
                                }
                            </div>
                        </div>
                    </div>
                }
            </div>
        </div>
        index++;
    }
    <div class="col-sm-12">
        <div class="row">
            @Html.ActionLink("Cancel", "Welcome", "Home", null, new { @class = "btn btn-default" })
            <button class="btn btn-default" onclick="history.go(-1);">Previous</button>
            <button type="submit" class="btn btn-default">Next</button>
        </div>
    </div>
}

查看我在视图中添加的隐藏字段。这样做的技巧,即使发布您的数据与破碎的序列。

我能够通过采用使用索引整数的想法并从上面的答案中增加它并在我的视图中以不同的方式实现这个想法来将模型返回到控制器:

@model Portal.Models.ViewModel.CreateApplicationViewModel
@{
    ViewBag.Title = "Step 4/5";
    Layout = "~/Views/Shared/_Layout.cshtml";
}
@using System.Linq
<h4>Case Data Details</h4>
@using (Html.BeginForm("Step4", "CreateApplication", FormMethod.Post, new { @class = "col-sm-12" }))
{
    int index = 0;
    foreach (var group in Model.Step4.DataDetails.GroupBy(item => item.GroupDesc))
    {
        <div class="panel panel-primary">
            <div class="panel-heading">@Html.Encode(group.Key)</div>
            <div class="panel-body">
                @for (var i = 0; i < group.Count(); i++)
                {
                    <div class="form-group">
                        <div class="row">
                            <div class="col-xs-6">
                                <label class="form-label">@Model.Step4.DataDetails[i].DetailDesc</label>
                            </div>
                            <div class="col-xs-6">
                                @Html.TextBoxFor(val => val.Step4.DataDetails[index].TextValue)
                                @Html.HiddenFor(val => val.Step4.DataDetails[index].GroupCode)
                            </div>
                        </div>
                    </div>
                    index++;
                }
            </div>
        </div>
    }
    <div class="col-sm-12">
        <div class="row">
            @Html.ActionLink("Cancel", "Welcome", "Home", null, new { @class = "btn btn-default" })
            <button class="btn btn-default" onclick="history.go(-1);">Previous</button>
            <button type="submit" class="btn btn-default">Next</button>
        </div>
    </div>
}

视图中的上述代码为每个元素提供了适当的索引,并允许我发布