2012-05-11 29 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