2012-07-14 115 views
11

我们一直试图让编辑器模板与动态属性一起工作 - 无济于事。也许你们中的一个人可以帮助我们。Asp.Net MVC 3动态属性编辑器

这里大致是我们班:

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="[email protected](i)[email protected](j)__Value">@criterionDisplayName</label> 
     @Html.Editor(name, type) 
    } 
} 

这并显示例如一个复选框正确的,但它不使用值正确设置复选框状态(如果criterion.Value为true,则检查)。其他类型也一样,例如ints。 (它会在POST请求后正确填写表单,但这是因为MVC使用临时模型来重新创建用户输入。)

尽管我们已经尝试和研究过了:是否可以使用编辑器模板属性类型dynamic?如果是的话 - 我们如何才能使它工作? (我们不希望根据可能的类型来辨别,我们希望MVC框架能够根据实际类型使用正确的编辑器模板。)

回答

15

动态效果不太适合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类型。

+0

它适用于强类型视图。我试图改变索引视图不使用强类型视图:删除了@ @模型IList '并使用了@ @ var模型=(IList )模型; }'。然后我尝试'@ Html.Editor(“model [”+ i +“] .Value”,“Criterion_”+ model [i] .Value.GetType()。Name)',但它给了我一个错误 - _The model传入字典的项目为空,但是此字典需要类型为'System.Int32'的非空模型项目._我在做什么错误?调试告诉我,在Index-View中GetType()。Name是'Int32'。 – toni 2012-07-16 14:27:55

+0

顺便说一句 - 我们需要使用非强类型的视图,因为我们使用的是第三方框架(来自Orchard的ContentShape)。 – toni 2012-07-16 14:33:04

+0

我们用'object'结束了上面的Darins方法。我们只需转换动态ViewModel并将其传递给强类型编辑器模板。谢谢Darin,宝贵的意见。 – toni 2012-07-19 14:38:34