带有 List<BaseClass> 的 ViewModel和编辑器模板 [英] ViewModel with List&lt;BaseClass&gt; and editor templates

查看:25
本文介绍了带有 List<BaseClass> 的 ViewModel和编辑器模板的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个视图,其中列出了添加到平面图中的表格.表格派生自 TableInputModel 以允许 RectangleTableInputModelCircleTableInputModel

I have a view that lists tables being added to a floor plan. Tables derive from TableInputModel to allow for RectangleTableInputModel, CircleTableInputModel, etc

ViewModel 有一个 TableInputModel 列表,它们都是派生类型之一.

The ViewModel has a list of TableInputModel which are all one of the derived types.

我对每个派生类型都有一个局部视图,并给出了混合派生类型的List,框架知道如何呈现它们.

I have a partial view for each of the derived types and given a List of mixed derived types the framework knows how to render them.

但是,在提交表单时,类型信息会丢失.我曾尝试使用自定义模型绑定器,但由于类型信息在提交时丢失,因此无法使用...

However, on submitting the form the type information is lost. I have tried with a custom model binder but because the type info is lost when it's being submitted, it wont work...

有人试过吗?

推荐答案

假设您有以下模型:

public abstract class TableInputModel 
{ 

}

public class RectangleTableInputModel : TableInputModel 
{
    public string Foo { get; set; }
}

public class CircleTableInputModel : TableInputModel 
{
    public string Bar { get; set; }
}

以及以下控制器:

public class HomeController : Controller
{
    public ActionResult Index()
    {
        var model = new TableInputModel[]
        {
            new RectangleTableInputModel(),
            new CircleTableInputModel()
        };
        return View(model);
    }

    [HttpPost]
    public ActionResult Index(TableInputModel[] model)
    {
        return View(model);
    }
}

现在你可以写视图了.

主视图Index.cshtml:

@model TableInputModel[]
@using (Html.BeginForm())
{
    @Html.EditorForModel()
    <input type="submit" value="OK" />
}

和相应的编辑器模板.

~/Views/Home/EditorTemplates/RectangleTableInputModel.cshtml:

@model RectangleTableInputModel
<h3>Rectangle</h3>
@Html.Hidden("ModelType", Model.GetType())
@Html.EditorFor(x => x.Foo)

~/Views/Home/EditorTemplates/CircleTableInputModel.cshtml:

@model CircleTableInputModel
<h3>Circle</h3>
@Html.Hidden("ModelType", Model.GetType())
@Html.EditorFor(x => x.Bar)

最后缺少的谜题是 TableInputModel 类型的自定义模型绑定器,它将使用发布的隐藏字段值来获取类型并实例化正确的实现:

and final missing peace of the puzzle is the custom model binder for the TableInputModel type which will use the posted hidden field value to fetch the type and instantiate the proper implementation:

public class TableInputModelBinder : 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(TableInputModel), new TableInputModelBinder());

就这些.现在在 Index Post 操作中,模型数组将使用正确的类型正确初始化.

and that's pretty much all. Now inside the Index Post action the model array will be properly initialzed with correct types.

这篇关于带有 List<BaseClass> 的 ViewModel和编辑器模板的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆