【问题标题】:Html.DropDownListFor selecting item based on ModelState rather than ModelHtml.DropDownList用于基于ModelState而不是Model选择item
【发布时间】:2014-06-24 12:57:52
【问题描述】:

在 asp.net mvc(在我的例子中是 v5)中,当您将模型回传到控制器,然后使用不同于回传模型的模型渲染视图,然后Html.DropDownListFor 将根据回传的模型中的数据而不是传递给视图的模型来选择所选项目。

这是为什么?

这是一个例子。当您在第一个下拉列表中选择一个新项目时,表单会回发,如果第一个下拉列表选择了 id=2,则 selectedId2 会更改,并且第二个下拉列表应该呈现选择的第二个项目.然而事实并非如此。虽然视图中的模型对象确实具有新的 selectedId2 = 2 值,但底层的 DropDownListFor 从 ViewState.ModelState 对象而不是 ViewState.Model 获取选定值。怎样才能让 DropDownListFor 仅基于传递给视图的模型进行渲染?

控制器:

public class HomeController : Controller
{
    public ActionResult Index()
    {
        var defaultModel = getModel();
        return View(defaultModel);
    }

    [HttpPost]
    public ActionResult Index(Model1 postedModel)
    {
        var defaultModel = getModel();

        if (postedModel.selectedId1 == 2)
        {
            defaultModel.selectedId1 = 2;
            defaultModel.selectedId2 = 2;
        }

        return View(defaultModel);
    }

    private Model1 getModel()
    {
        var items1 = new[]
        {
            new
            {
                Name = "Item 1-1",
                Id = "1"
            },
            new
            {
                Name = "Item 1-2",
                Id = "2"
            }
        };

        var items2 = new[]
        {
            new
            {
                Name = "Item 1-1",
                Id = "1"
            },
            new
            {
                Name = "Item 2-2",
                Id = "2"
            }
        };

        return new Model1
        {
            selectedId1 = 1,
            selectedId2 = 1,
            SelectList1 = new SelectList(items1, "Id", "Name", 1),
            SelectList2 = new SelectList(items2, "Id", "Name", 1)
        };
    }


}

视图模型:

public class Model1
{
    public SelectList SelectList1 { get; set; }
    public SelectList SelectList2 { get; set; }
    public int selectedId1 { get; set; }
    public int selectedId2 { get; set; }
}

观点:

@model Model1

@using (Html.BeginForm(FormMethod.Post))
{
    <div>
        @Html.DropDownListFor(m => m.selectedId1, Model.SelectList1, new { title = "Select 1", onchange = "this.form.submit();" })
        @Html.DropDownListFor(m => m.selectedId2, Model.SelectList2, new { title = "Select 2", onchange = "this.form.submit();" })
    </div>
}

编辑:我找到的一个解决方案: 在执行 View() 之前添加这一行会清除发布的模型,以便 DropDownListFor 助手使用传递给视图的模型:

ViewData.ModelState.Clear();

【问题讨论】:

    标签: asp.net asp.net-mvc asp.net-mvc-5


    【解决方案1】:

    如果你使用合适的SelectList构造函数,你可以指定选择的值:

    SelectList Constructor (IEnumerable, String, String, Object)

    最后一个参数是选中项,必须是IEnumerable的一个对象。

    您正在使用此构造函数,但将 1 指定为值。它应该类似于items1[0]

    【讨论】:

    • 这不只是设置要选择的默认项,它会被在 DropDownListFor() 调用中使用的模型/lambda 表达式中提供的选定项 id 覆盖?
    • DropDownListFor的MVC代码比较纠结。如果你跟着它,你会看到一个SelectInternal 类,它使用SelectList 的每个项目的Selected 属性来决定是否选择了一个值(SelectList 是一个@ 987654331@.SelectListItem 有一个Selected 属性)。一路走来,似乎没有一个地方可以修改 Selected 属性。我一直这样使用它,并且从来没有遇到过麻烦(至少在我的使用模式中)。它不适合你吗?
    • 如果您将DropDowListFor 与其他助手进行比较,会有很大的不同:在其他助手代码中,您可以看到他们收到了模型。 DropDownListFor 没有收到。
    • 不,我认为您错过了我问题的主要部分。在视图模型或 SelectList 的构造函数中放置什么作为选定项都没有关系,因为模型中发布到操作的数据会被使用。如果您查看 DropDownListFor 的 MVC 代码,您会看到所选值是从 ViewState.ModelState 中提取的,而不是从 ViewState.Model 中提取的。当视图在 POST 上呈现时存在我的问题 - 当视图呈现为 GET 时没有问题。我确实发现添加 ViewData.ModelState.Clear();在我在控制器操作中调用 View() 之前。
    • 您尝试过我的解决方案但失败了吗?如果是这样,请告诉我,我会尝试用概念证明来重复它。谢谢!
    猜你喜欢
    • 2023-03-05
    • 2014-08-30
    • 2012-11-29
    • 1970-01-01
    • 2012-03-22
    • 1970-01-01
    • 1970-01-01
    • 2018-06-20
    • 1970-01-01
    相关资源
    最近更新 更多