C# 如何在同一视图上编辑多个类型(具有相同的基础)?
假设我有两个类一个基类:C# 如何在同一视图上编辑多个类型(具有相同的基础)?,c#,asp.net-mvc,razor,C#,Asp.net Mvc,Razor,假设我有两个类一个基类: public class BaseModel { } 还有几个孩子: public class FooModel : BaseModel { } public class BarModel : BaseModel { } 现在我的观点是,我希望有这样一个模型: @model IEnumerable<BaseModel> 我怎样才能做到这一点?(将列表中的项目返回到其子类类型?) 我在想我可以试着用TryUpdateModel吗 感谢您的帮助。您
public class BaseModel {
}
还有几个孩子:
public class FooModel : BaseModel {
}
public class BarModel : BaseModel {
}
现在我的观点是,我希望有这样一个模型:
@model IEnumerable<BaseModel>
我怎样才能做到这一点?(将列表中的项目返回到其子类类型?)
我在想我可以试着用TryUpdateModel吗
感谢您的帮助。您需要指定集合中项目的索引 以下是控制器代码:
public class HomeController : Controller
{
//
// GET: /Home/
public ActionResult Index()
{
return
View(new List<BaseModel>() { new BarModel() { BaseProp = "Bar" }, new FooModel() { BaseProp = "Foo" } });
}
[HttpPost]
public ActionResult Index(IList<BaseModel> model)
{
return this.View(model);
}
}
这是自定义模型绑定器的示例实现:
public class BaseModelBinder : DefaultModelBinder
{
public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
// call to get the BaseModel data so we can access the Type property
var obj = base.BindModel(controllerContext, bindingContext);
var bm = obj as BaseModel;
if(bm != null)
{
//call base.BindModel again but this time with a new
// binding context based on the spefiic model type
obj = base.BindModel(
controllerContext,
new ModelBindingContext(bindingContext)
{
ModelMetadata =
ModelMetadataProviders.Current.GetMetadataForType(null, Type.GetType(bm.Type)),
ModelName = bindingContext.ModelName
});
}
return obj;
}
}
您需要在应用程序启动时注册自定义活页夹:
ModelBinders.Binders.Add(typeof(BaseModel), new BaseModelBinder());
请记住,当您在MVC中发布表单时,实际上并没有从浏览器中获取对象。您得到了一组键值对,框架“神奇地”为您构建了它所期望的对象。它需要哪些对象是由代码中的静态类型签名决定的,@model指令或控制器方法参数。(不确定是哪个,我对ASP.NET MVC的细节不太熟悉。)它不会自动记住以前发送的对象。因此,我将不得不使用TryUpdate…:S uncool。我已经这样做了,这不是问题,我将值作为基本模型完美地返回,但我想将它们转换为它们的实例类型。好的,哇,让我试一试,然后再打给你-提前谢谢。@shenku请记住,我在BaseModelBinder类的CreateModel方法中添加了一行额外的代码。否则,FooModel和BarModel类的特定属性没有正确绑定。@shenku进行了一些重构。现在更简单,更容易阅读。
@using MvcApplication1.Models
@model IList<MvcApplication1.Models.BaseModel>
@{
ViewBag.Title = "title";
//Layout = "_Layout";
}
<h2>title</h2>
@using (Html.BeginForm())
{
for (int i = 0; i < Model.Count; i++)
{
@Html.EditorFor(p => p[i])
}
<input type="submit" value="Save" />
}
<input class="text-box single-line" name="[0].BaseProp" type="text" value="Bar" />
namespace MvcApplication1.Models
{
using System.Web.Mvc;
public class BaseModel
{
public string BaseProp { get; set; }
[HiddenInput(DisplayValue = false)]
public virtual string Type
{
get
{
return _type ?? this.GetType().FullName;
}
set
{
_type = value;
}
}
private string _type;
}
public class FooModel : BaseModel
{
public string FooProp { get; set; }
}
public class BarModel :BaseModel
{
public string BarProp { get; set; }
}
}
public class BaseModelBinder : DefaultModelBinder
{
public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
// call to get the BaseModel data so we can access the Type property
var obj = base.BindModel(controllerContext, bindingContext);
var bm = obj as BaseModel;
if(bm != null)
{
//call base.BindModel again but this time with a new
// binding context based on the spefiic model type
obj = base.BindModel(
controllerContext,
new ModelBindingContext(bindingContext)
{
ModelMetadata =
ModelMetadataProviders.Current.GetMetadataForType(null, Type.GetType(bm.Type)),
ModelName = bindingContext.ModelName
});
}
return obj;
}
}
ModelBinders.Binders.Add(typeof(BaseModel), new BaseModelBinder());