【问题标题】:Can I dynamically assign the @model type in an EditorTemplate?我可以在 EditorTemplate 中动态分配 @model 类型吗?
【发布时间】:2012-08-16 08:47:08
【问题描述】:

我有一个图像上传器编辑器模板,该模板目前是 MultiImageUploader 视图模型的强类型。问题是我有一些自定义数据验证属性,我想在直接调用编辑器模板的视图模型中使用它们,而不是通过 MultiImageUploader 视图模型进行路由。

我不想用预设的验证属性调用 MultiImageUploader 视图模型,而是这样做:

public class CreateBrandViewModel
{
    .....<snipped>.....

    [PermittedFileExtensions("jpg, jpeg, png, gif")]
    [MaxFileSize("2MB")]
    [UIHint("MultiImageUploader")]
    public HttpPostedFileBase Image { get; set; }

  //Currently this view model looks like this:
  //public MultiImageUploader Image { get; set; } <-- seperate view model 

}

我目前无法使用我的首选方式,因为我的编辑器模板不是针对 CreateBrandViewModel 进行强类型化的。有没有办法可以将调用视图模型的 @model 传递到编辑器模板视图中? :

@model // Here? //
<div class="editor-field">
     @Html.TextBoxFor(x => x.Image, new { type = "file" })
     @Html.ValidationMessageFor(x => x.Image)
</div>

编辑 1

只是为了澄清,我想这样做的原因是因为我想从图像上传器更改为通用文件上传器 - 这需要在不同的视图模型上使用不同的验证属性。为此,目前我需要为每个稍微不同的验证参数变体创建不同的视图模型和编辑器模板。

编辑 2:关于@Joel Athertons 的回答

我在尝试实现这一点时遇到了一些问题(或者我可能只是没有正确理解)。

我已经创建了接口和抽象类。我的 CreateBrandViewModel 现在继承自 FileUpload。 FileUpload 当前为空,没有共享属性。当我尝试 model.GetType().Name 时,我得到一个“对象引用未设置为对象的实例”。错误。代码如下:

Controller 将 CreateBrandViewModel 传递给视图:

    [HttpGet]
    public ActionResult Create()
    {
        var model = new CreateBrandViewModel();
        model.IsActive = true;

        return View(model);
    }

Create 视图然后调用 EditorTemplate:

@model CumbriaMD.Infrastructure.ViewModels.BrandViewModels.CreateBrandViewModel 

@Html.EditorFor(model => model.File, "EditorTemplates/MultiImageUploader")

然后模板(为了简单起见)如下所示:

@model CumbriaMD.Infrastructure.ViewModels.FileUploadViewModels.FileUpload

@{
    var partialView = Model.GetType().Name;
}

<h1>@partialView</h1>

任何想法都将不胜感激:)

【问题讨论】:

    标签: c# asp.net-mvc-3 templates editor viewmodel


    【解决方案1】:

    我处理这个问题的方法是有一个接口,所有允许上传的模型都将实现该接口。如果你真的有共同的功能,我也会将它与一个具有任何共同属性、属性等的抽象模型结合起来。然后你的每个单独的模型要么继承抽象类(或者如果你不使用接口,则实现接口)类),然后您可以将其用作您的 @model 语句。然后,您可以简单地将任何一次性的部分拆分为可以做自己事情的部分视图。

    public interface IFileUploadModel
    {
        // any common properties would go here
    }
    
    public abstract class FileUploadModel : IFileUploadModel
    {
        // implement the common stuff
    }
    
    public class CreateBrandViewModel : FileUploadModel
    {
        [PermittedFileExtensions("jpg, jpeg, png, gif")]
        [MaxFileSize("2MB")]
        [UIHint("MultiImageUploader")]
        public HttpPostedFileBase Image { get; set; }
    }
    
    public class SomeOtherUploadModel : FileUploadModel
    {
        // Other special stuff here
    }
    

    然后在你的模板中。

    @model FileUploadModel
    
    @{
        // Common output code that they all do
    
        // Then the special stuff
        if (model.GetType().Name == "CreateBrandViewModel")
        {
            // Render the partial and pass it the model
            Html.RenderPartial("CreateBrandPartialView", Model);
        }
    }
    

    【讨论】:

    • 嘿,抱歉花了一些时间来回复 - 昨天被捆绑了!这看起来很棒,谢谢,好主意。今早实施。但有一件事是 if 语句 - 我是否必须为每个实现 FileUploadModel 的模型编写 if 语句(考虑到我还没有尝试过)?谢谢!
    • Hrrmm 我想我现在明白了一点。但是,如果我可以获取模型的类型并使用严格的命名约定,我什至可以正则表达式 model.GetType().Name 字符串以删除“ViewModel”并将其放入 Html.RenderPartial(regExResult + "PartialView ), 模型); ?
    • 在实现这个好主意时遇到了一些问题,更新了原始帖子:)
    【解决方案2】:

    如果你的班级是这样的:

    public class CreateBrandViewModel
    {
        [PermittedFileExtensions("jpg, jpeg, png, gif")]
        [MaxFileSize("2MB")]
        [UIHint("MultiImageUploader")]
        public HttpPostedFileBase Image { get; set; }
    }
    

    并且您有一个名为 MultiImageUploader.cshtml 的 EditorTemplate,那么它看起来像:

    @model HttpPostedFileBase
    
    @Html.LabelFor(m => m)
    @Html.TextBoxFor(x => x, new { type = "file" })
    @Html.ValidationMessageFor(x => x)
    

    你会在你的整体视图中呈现它:

    @Html.EditorFor(m => m.Image)
    

    【讨论】:

    • 在我看来这会产生编译错误,因为该类不继承 HttpPostedFileBase 所以不能在 @model 语句后面使用。
    • 如果使用@Html.EditorFor(m => m.Image) 则不是,它是模型的Image 属性的编辑器模板。
    猜你喜欢
    • 2023-02-08
    • 1970-01-01
    • 2011-11-03
    • 2021-05-19
    • 1970-01-01
    • 1970-01-01
    • 2018-09-12
    • 2012-12-20
    相关资源
    最近更新 更多