MVC3 HTML helper doesn't update DropdownListFor on Submit the form

北城余情 提交于 2019-12-08 19:54:26

Model

public class TestModel {
    public String Color { get; set; }
    public SelectList Colors {get;set;} }

Controller

public ActionResult Index() {
        var model = new TestModel();
        model.Color="Blue";
        var colors =new List<SelectListItem>() { new SelectListItem() { Text =  "Blue", Value = "Blue" }, new SelectListItem() { Text = "Red", Value = "red" } };
        model.Colors = new SelectList(colors,"Text","Value");

        return View(model);
    }

[HttpPost] public ActionResult Index(TestModel model) {
        model.Color="Red";

        var colors =new List<SelectListItem>() { new SelectListItem() { Text =  "Blue", Value = "Blue" }, new SelectListItem() { Text = "Red", Value = "red" } };
        model.Colors = new SelectList(colors,"Text","Value");

        return View(model); }

View

@using (Html.BeginForm()) {
    <div>
        @Html.DropDownListFor(m => m.Color, Model.Colors, new { @class = "w200" })
       <input type="submit" />
     </div> 
}

You need to include all colors in your Post action.

Also do not use ViewData but add the items to you view model:

public class TestModel {
    public String Color { get; set; }
    IEnumerable<SelectListItem> AvailableColors {get;set;}
}

But since view models are intended to be used to abstract away your models you could do something like:

public class TestModel {
    public TestModel(IEnumerable<string> colors)
    {
        AvailableColors = colors.Select(c => new SelectListItem{Text=c, Value = c});
    }

    public String Color { get; set; }
    IEnumerable<SelectListItem> AvailableColors {get;}
}

And in your controller:

public ActionResult Index() {
    var model = new TestModel(new string[]{"Red", "Green", "Blue"});
    model.Color="Blue";
    return View(model);
}

Okay guys, the problem is not about the way you implement this scenario, the problem here is ModelState. I POST to the Action and return the same view. The second time the view is rendered it will look at the ModelState and use those values to fill the controls. So simply we need to clear the ModelState before returning the View.

Model.cs

public class TestModel {
    public String Color { get; set; }
}

Controller.cs

public ActionResult Index() {
        var model = new TestModel();
        model.Color="Blue";
        ViewData["Colors"]=new List<SelectListItem>() { new SelectListItem() { Text =  "Blue", Value = "Blue" }, new SelectListItem() { Text = "Red", Value = "Red" } };


        return View(model);
    }

[HttpPost]
public ActionResult Index(TestModel model) {
        model.Color="Red";
        ViewData["Colors"]=new List<SelectListItem>() { new SelectListItem() { Text =  "Blue", Value = "Blue" }, new SelectListItem() { Text = "Red", Value = "Red" } };

        ***ModelState.Clear();***
        return View(model);
}

Index.cs

@using (Html.BeginForm()) {
@Html.DropDownListFor(m => m.Color, ViewData["Colors"], new { @class = "w200" })
<input type="submit" />

}

Cheeeeeers

Becuzz

In order to make the dropdown list change what is selected you have to set the Selected attribute of the select list item corresponding to the textbox value to true. Something like this: (Note: I did not compile and test this. Tweaks may be needed to get it to compile. Also, I assumed that if a color was not in the list it should be added.)

[HttpPost]
public ActionResult Index(TestModel model) {
        model.Color="Red";
        var colors = new List<SelectListItem>() { new SelectListItem() { Text =  "Blue", Value = "Blue" }, new SelectListItem() { Text = "Red", Value = "Red" } };

        SelectListItem selectedColor = colors.Where(c => c.Text == model.Color).FirstOrDefault();
        if (selectedColor != null)
        {
            selectedColor.Selected = true;
        }
        else
        {
            colors.Add(new SelectListItem() { Text = model.Color; Value = model.Color; Selected = true; };
        }
        ViewData["Colors"] = colors;
        return View(model);
}

EDIT

After doing some testing and digging, it appears that you will need to use javascript to do this as explained in this SO question. Another option is to roll your own helper.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!