2012-05-11 30 views
5

这是从MVC3 Razor httppost return complex objects child collections后续问题。mvc3 razor editortemplate抽象类

我给出的例子非常简单。子集合实际上是所有来自抽象基类的对象的集合。所以这个集合有一个基类列表。

我已经为每个派生类创建了一个模板,并尝试使用如果孩子是类型的,然后将模板名称作为字符串。模板呈现给视图,但未在帖子后面填充。

我不知道如何使用编辑器的模板来选择正确的模板,并获取信息编组回到父容器内的子对象。

回答

8

您可以使用自定义模型联编程序。我们举个例子吧。

型号:

public class MyViewModel 
{ 
    public IList<BaseClass> Children { get; set; } 
} 

public abstract class BaseClass 
{ 
    public int Id { get; set; } 

    [HiddenInput(DisplayValue = false)] 
    public string ModelType 
    { 
     get { return GetType().FullName; } 
    } 
} 

public class Derived1 : BaseClass 
{ 
    public string Derived1Property { get; set; } 
} 

public class Derived2 : BaseClass 
{ 
    public string Derived2Property { get; set; } 
} 

控制器:

public class HomeController : Controller 
{ 
    public ActionResult Index() 
    { 
     var model = new MyViewModel 
     { 
      Children = new BaseClass[] 
      { 
       new Derived1 { Id = 1, Derived1Property = "prop1" }, 
       new Derived2 { Id = 2, Derived2Property = "prop2" }, 
      } 
     }; 
     return View(model); 
    } 

    [HttpPost] 
    public ActionResult Index(MyViewModel model) 
    { 
     // everything will be fine and dandy here 
     ... 
    } 
} 

视图(~/Views/Home/Index.cshtml):为Dervied1类型

@model MyViewModel 

@using (Html.BeginForm()) 
{ 
    for (int i = 0; i < Model.Children.Count; i++) 
    { 
     @Html.EditorFor(x => x.Children[i].ModelType) 
     <div> 
      @Html.EditorFor(x => x.Children[i].Id) 
      @Html.EditorFor(x => x.Children[i])  
     </div> 
    } 

    <button type="submit">OK</button> 
} 

编辑器模板(~/Views/Home/EditorTemplates/Derived1.cshtml):

@model Derived1 
@Html.EditorFor(x => x.Derived1Property) 

,为Dervied2类型(~/Views/Home/EditorTemplates/Derived2.cshtml)编辑模板:

@model Derived2 
@Html.EditorFor(x => x.Derived2Property) 

现在,所有剩下的就是将使用隐藏字段的值来实例化适当的类型集合中的自定义模型绑定:

public class BaseClassModelBinder : DefaultModelBinder 
{ 
    protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType) 
    { 
     var typeValue = bindingContext.ValueProvider.GetValue(bindingContext.ModelName + ".ModelType"); 
     var type = Type.GetType(
      (string)typeValue.ConvertTo(typeof(string)), 
      true 
     ); 
     var model = Activator.CreateInstance(type); 
     bindingContext.ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(() => model, type); 
     return model; 
    } 
} 

将在Application_Start注册:

ModelBinders.Binders.Add(typeof(BaseClass), new BaseClassModelBinder()); 
+0

太棒了......那是一种享受......我不得不回去工作,让笔记本电脑试试这个,因为它看起来很棒......在我开始的周末,甚至开始之前 – Jon