在新视图中使用时,ViewModel不绑定

时间:2015-09-23 15:16:13

标签: asp.net-mvc binding viewmodel

我能够在我的index.cshtml页面上的表单上最初将视图模型传递给编辑器模板页面。在索引页面上,我有一个提交按钮,将表单结果(编辑器模板中的单选按钮组)发布回控制器,在HttpPost方法中,它将此模型传递给部分视图,该视图显示在模式弹出窗口中。所有这一切都显示了所选的表单元素,但它禁用了用户的单选按钮。用户可以从此处返回(关闭窗口)或确认表单结果。当用户单击确认按钮时,它应该将viewmodel传递回控制器到另一个HttpPost方法,然后该方法将处理表单结果并返回最终的确认视图。但是当我尝试将视图模型从模态弹出窗口传递回控制器时,它不会保留绑定。我试图确保所有内容都通过Hidden输入绑定,但我必须在某处丢失某些内容。也许我会以错误的方式解决这个问题。我只需要基本保持viewmodel绑定从初始帖子,并能够在用户从模态弹出窗口确认选择后处理。什么是最好的方法来实现这一点,而不必在那里进行会话黑客?

索引

@using (Html.BeginForm("Index", "Home", FormMethod.Post, new { id = "ballotForm" }))
{
   @Html.AntiForgeryToken()
   @(Html.EditorFor(m => m.BallotViewModel, new ViewDataDictionary(ViewData)
    {
       TemplateInfo = new System.Web.Mvc.TemplateInfo
       {
         HtmlFieldPrefix = "BallotViewModel"
       }
     }))
<table class="col-sm-12">
   <tr>
      <td class="pull-right">
         <button type="submit" class="btn btn-primary" data-target="#modal-container" data-toggle="modal">Vote Management Ballot</button>
      </td>
   </tr>
</table>
}

控制器 - 初始发布到模态弹出窗口

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Index(HomeViewModel bModel)
{
    if (ModelState.IsValid)
    {
       //set property to identity view
       bModel.BallotViewModel[0].IsVoteConfirmationView = true;
       return PartialView("ViewVoteConfirmation", bModel);
    }         
 }

控制器 - 从模态弹出窗口确认提交后发布

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult ConfirmVote(HomeViewModel cModel)
{
    //Process form results here but model is null

    //Go to Thank You View
    return View();
}

ViewVoteConfirmation:

@model Ballot.WebUI.Models.HomeViewModel
<div class="row">
        @(Html.EditorFor(m => m.BallotViewModel, new ViewDataDictionary(ViewData) { TemplateInfo = new TemplateInfo { HtmlFieldPrefix = "BallotViewModel" } }))
    </div>

        @using (Html.BeginForm("ConfirmVote", "Home", FormMethod.Post, new { id = "ballotConfirmVoteForm" }))
        {
            @Html.AntiForgeryToken()
            <div class="row">

               @Html.EditorFor(m => m.BallotViewModel[0].Proposals, "Proposals", new ViewDataDictionary(ViewData)
               {
                   TemplateInfo = new TemplateInfo
                   {
                       HtmlFieldPrefix  = "Proposals"
                   }
               })

            </div>
            <div class="row">
                <div class="col-md-4 col-md-offset-4">
                    <button type="button" class="btn btn-default"
                            data-dismiss="modal">
                        Cancel
                    </button>
                    <button type="submit" id="approve-btn"
                            class="btn btn-danger">
                        Confirm
                    </button>
                </div>
            </div>
        }

ProposalViewModel:

public class ProposalViewModel
    {
        public int ProposalItemID { get; set; }
        public string ProposalItemTitle { get; set; }

        public string Option0_Name { get; set; }
        public string Option1_Name { get; set; }
        public string Option2_Name { get; set; }
        public string Option3_Name { get; set; }
        public string PercOfShare { get { return "% of Share"; }}

        public bool IsHeader { get; set; }
        public int TagOrder { get; set; }
        public int SelectedVoteOption { get; set; }
        public bool IsVoteConfirmationView { get; set; }
        public bool IsCumulative { get; set; }
        public int SharePercentage { get; set; }

        public List<VoteOptionViewModel> lVoteOptions { get; set; }
    }

提案:

@model List<Ballot.WebUI.Models.ProposalViewModel>

@for (int i = 0; i < Model.Count; i++)
{

    @Html.HiddenFor(m => m[i].ProposalItemID)
    @Html.HiddenFor(m => m[i].ProposalItemTitle)
    @Html.HiddenFor(m => m[i].Option0_Name)
    @Html.HiddenFor(m => m[i].Option1_Name)
    @Html.HiddenFor(m => m[i].Option2_Name)
    @Html.HiddenFor(m => m[i].Option3_Name)
    @Html.HiddenFor(m => m[i].PercOfShare)
    @Html.HiddenFor(m => m[i].IsHeader)
    @Html.HiddenFor(m => m[i].TagOrder)
    @Html.HiddenFor(m => m[i].SelectedVoteOption)
    @Html.HiddenFor(m => m[i].IsVoteConfirmationView)
    @Html.HiddenFor(m => m[i].IsCumulative)
    @Html.HiddenFor(m => m[i].lVoteOptions)
    @Html.HiddenFor(m => m[i].SharePercentage)

}

用于更改SharePercentage标签值的jquery脚本

$(function () {
    //When 'For' is Selected
    $('[class$=PercOfShareFor]').on('click', function (e) {
        if ($(this).is(':checked')) {
            var forMatches1 = 0;

            $('[class$=PercOfShareFor]').each(function (i, val) {
                if ($(this).is(':checked')) {
                    //check how many 'For' Vote Options are selected
                    forMatches1++;
                    //select the Share Percentage value label in the same row, and change the class to ForSelected (used as selector)
                    $(this).closest('td').next('td').next('td').find('.SharePercentage')
                        .removeClass("SharePercentage")
                        .addClass("SharePercentageForSelected");
                    //if the Share Percentage class (used as selector) was previously WithholdSelected then change to ForSelected
                    $(this).closest('td').next('td').next('td').find('.SharePercentageWithholdSelected')
                        .removeClass("SharePercentageWithholdSelected")
                        .addClass("SharePercentageForSelected");
                }
            });

            //divide total 'For' Selections by number of Director Proposals
            var forPercent1 = 100 / forMatches1;

            //format the percentage to display 2 decimal places if not a whole number
            var forPercent2 = Math.round(forPercent1 * 100) / 100;

            //Update 'For' Percentages
            $('[class$=SharePercentageForSelected]').text(forPercent2);
        }
    });
    //When 'Withhold' is Selected after initially selecting 'For'
    $('[class$=PercOfShareWithhold]').on('click', function (e) {
        if ($(this).is(':checked')) {
            var forMatches = 0;

            $('[class$=PercOfShareFor]').each(function (i, val) {
                if ($(this).is(':checked')) {
                    //check how many 'For' Vote Options are still selected
                    forMatches++;
                }
            });
            var withholdMatches = 0;
            $('[class$=PercOfShareWithhold]').each(function (i, val) {
                if ($(this).is(':checked')) {
                    //check how many 'Withhold' Vote Options are still selected
                    withholdMatches++;
                    //set the class to WithholdSelected
                    $(this).closest('td').next('td').find('.SharePercentageForSelected')
                        .removeClass("SharePercentageForSelected")
                        .addClass("SharePercentageWithholdSelected")
                        .text("0"); //Set 'Withhold' Percentage back to 0
                }
            });

            //divide total 'For' Selections by number of Director Proposals
            var forPercent1 = 100 / forMatches;

            //format the percentage to display 2 decimal places if not a whole number
            var forPercent2 = Math.round(forPercent1 * 100) / 100;

            //Update 'For' Percentages
            $('[class$=SharePercentageForSelected]').text(forPercent2);

        }
    });
});

2 个答案:

答案 0 :(得分:0)

你不能通过表格帖子做你想做的事情。浏览器将Post作为完整的HTML页面返回(即使您说它是部分服务器端)。您将需要使用某种形式的JavaScript来完成它,或者您需要使您的确认页面成为实际页面而不是模态弹出窗口。

基本前提是你需要通过javascript捕获提交(或按钮点击)然后显示模态。您可以使用第一个操作的结果填充模态,但您需要通过ajax而不是标准表单帖子提交表单。然后根据他们在模态中的选择,你可以提交或不提交表格。

已有多种资源可供您使用。这是一个展示如何display a confirmation for a delete action的人。然后你可以改变那个javascript,通过ajax加载你的第一个动作的结果,就像这篇关于加载MVC partial views using AJAX或者关于使用jQuery dialog for CRUD operations的关于加载{{3}}的文章一样,这个文章很可能。

答案 1 :(得分:0)

模型绑定修复是为BallotViewModel的EditorTemplate添加一个隐藏字段,这样当选择单选按钮时,标签不仅会更改值,而且隐藏字段也会更改值。

编辑模板

@ Html.HiddenFor(m =&gt; Model.Proposals [i] .SharePercentage,new {@class =&#34; hdnSharePercentage&#34;}) @ Html.LabelFor(m =&gt; Model.Proposals [i] .lVoteOptions [j] .SharePercentage,Model.Proposals [i] .lVoteOptions [j] .SharePercentage,new {@class =&#34; SharePercentage&#34; })

的jQuery        $(本).closest(&#39; TD&#39;)。下一个(&#39; TD&#39;)。下一个(&#39; TD&#39;)。找到(&#39; .hdnSharePercentageWithholdSelected&# 39)     .removeClass(&#34; hdnSharePercentageWithholdSelected&#34)     .addClass(&#34; hdnSharePercentageForSelected&#34);