【问题标题】:Asp.Net MVC 3 Editor for dynamic property用于动态属性的 Asp.Net MVC 3 编辑器
【发布时间】:2012-07-14 18:27:44
【问题描述】:

我们一直在尝试让 Editor-Template 与动态属性一起使用 - 无济于事。也许你们中的一个可以帮助我们。

这大概是我们的班级:

public class Criterion
{
    ...
    public string Text { get; set; }
    public dynamic Value { get; set; }
    public Type Type { get; set; }
    ...
}

我们的 razor 视图获得一个模型,其中包含一个部分列表,每个部分都包含一个标准列表。 (我们在运行时获得这些信息。)所有这些条件都应该在编辑模式下显示 - 关于它们的实际类型:(摘录)

@for (int i = 0; i < model.Sections.Count(); i++)
{
    for (int j = 0; j < model.Sections[i].Criteria.Count(); j++)
    {
        var criterion = model.Sections[i].Criteria[j];
        var type = criterion.Type.Name;
        var name = "Sections[" + i + "].Criteria[" + j + "].Value";
        var criterionDisplayName = criterion.Text;
        <label for="Sections_@(i)__Criteria_@(j)__Value">@criterionDisplayName</label>
        @Html.Editor(name, type)
    }
}

这确实正确显示了一个复选框,但它没有使用该值来正确设置复选框状态(检查条件。值是否为真)。其他类型也是如此,例如ints。 (它确实在 POST 请求后正确填写表单,但这是因为 MVC 使用临时模型来重新创建用户输入。)

正如我们所尝试和研究的那样:是否可以使用带有dynamic 类型属性的编辑器模板?如果是 - 我们怎样才能让它发挥作用? (我们不希望根据可能的类型来辨别。我们希望 MVC 框架根据实际类型使用正确的 Editor 模板。)

【问题讨论】:

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


    【解决方案1】:

    动态不适合 ASP.NET MVC。他们让我想起了ViewBag,我讨厌ViewBag,因为我的身体很深。所以我会采取不同的方法。

    我们以下面的模型为例:

    public class Criterion
    {
        public string Text { get; set; }
        public object Value { get; set; }
    }
    

    值可以是您希望处理的任何类型。

    现在您可以拥有一个填充此模型的控制器:

    public class HomeController : Controller
    {
        public ActionResult Index()
        {
            var model = new[]
            {
                new Criterion { Text = "some integer", Value = 2 },
                new Criterion { Text = "some boolean", Value = true },
                new Criterion { Text = "some string", Value = "foo" },
            };
            return View(model);
        }
    }
    

    然后是对应的视图:

    @model IList<Criterion>
    
    @using (Html.BeginForm())
    {
        for (int i = 0; i < Model.Count; i++)
        {
            <div>
                @Html.LabelFor(x => x[i], Model[i].Text)
                @Html.EditorFor(x => x[i].Value, "Criterion_" + Model[i].Value.GetType().Name)
            </div>
        }
    
        <button type="submit">OK</button>
    }
    

    现在对于您要处理的每种类型,您都可以定义一个相应的编辑器模板:

    ~/Views/Shared/EditorTemplates/Criterion_String.cshtml:

    @model string
    @Html.TextBoxFor(x => x)
    

    ~/Views/Shared/EditorTemplates/Criterion_Boolean.cshtml:

    @model bool
    @Html.CheckBoxFor(x => x)
    

    ~/Views/Shared/EditorTemplates/Criterion_Int32.cshtml:

    @model int
    @{
        var items = Enumerable
            .Range(1, 5)
            .Select(x => new SelectListItem 
            { 
                Value = x.ToString(), 
                Text = "item " + x 
            });
    }
    
    @Html.DropDownListFor(x => x, new SelectList(items, "Value", "Text", Model))
    

    显然,在视图中显示此模型只是第一步。我想您会想要获取用户在 POST 控制器操作中输入的值以进行某些处理。在这种情况下,一些小的调整是必要的。我们需要添加一个自定义模型绑定器,它能够在运行时实例化正确的类型,并将具体类型作为每行的隐藏字段包含在内。我已经在this post 中展示了一个示例。另请注意,在此示例中,我使用了一个基类,而不是直接使用 object 类型。

    【讨论】:

    • 它适用于强类型视图。我尝试将索引视图更改为不使用强类型视图:删除@model IList&lt;Criterion&gt; 并使用@{ var model = (IList&lt;Criterion&gt;)Model; }。然后我尝试@Html.Editor("model[" + i + "].Value", "Criterion_" + model[i].Value.GetType().Name),但它给了我一个错误 - 传入字典的模型项是空的,但是这个字典需要一个非空的'System.Int32'类型的模型项。什么我做错了吗?调试告诉我 GetType().Name 在索引视图中是 Int32
    • 顺便说一句——我们需要使用非强类型视图,因为我们使用的是第三方框架(来自 Orchard 的 ContentShape)。
    • 我们最终使用了 object 的 Darins 方法。我们只需要转换动态 ViewModel 并将其传递给强类型编辑器模板。感谢 Darin 提供的宝贵意见。
    • EditorTemplates 是要走的路。
    猜你喜欢
    • 2011-08-14
    • 1970-01-01
    • 1970-01-01
    • 2012-06-19
    • 1970-01-01
    • 2011-06-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多