ASP.NET MVC:使用interface作为模型创建动态视图

时间:2014-05-07 14:59:27

标签: asp.net-mvc asp.net-mvc-5

所以我有一个这样的界面:

public interface ISettings
    {
        string Name { get; }
    }

和各种实现,例如:

public class SettingsA : ISettings
{
    public string Name { get { return "Example A"; } }

    public string CustomAttributeA1 { get; set; }

    public string CustomAttributeA2 { get; set; }
}

public class SettingsB : ISettings
{
    public string Name { get { return "Example B"; } }

    public string CustomAttributeB1 { get; set; }

    public string CustomAttributeB2 { get; set; }
}

现在我遇到了需要创建动态UI的问题(将ISettings作为模型传递,并根据每个实现的属性生成控件)。所以我有这个:

Edit.cshtml:

@model ISettings

@Html.EditorForModel(Model)

这很好地产生了必需的字段,但问题是我无法轻松自定义它(例如:为Bootstrap添加css类或我可能想要的任何其他CSS)。我想我可以使用基于HTML的CSS选择器标签..但似乎不是理想的方法。这个问题有一些很好的解决方法吗?处理这种情况的最佳方法是什么?

2 个答案:

答案 0 :(得分:0)

尝试使用一些HTML帮助程序,例如:

public static class MyHtmlExtensions
{
   public static string GetCssForMyDiv(this HtmlHelper htmlHelper)
   {
      if (htmlHelper.ViewData.Model is SettingsA) return "class-a";
      else if (htmlHelper.ViewData.Model is SettingsB) return "class-b";
      else return "";
   }
}

从未在之前完成此操作,但应该可以正常工作。

你会有类似的事情:

<div class="class-base my-class my-div-style @Html.GetCssForMyDiv()">
   Check my CSS classes!
</div>

你可以用IDisposable玩一点,并且有一些很酷的东西:

@using(var div = Html.BeginDivWithCustomCssClassPerType())
{
   <span>Check my CSS classes!</span>
}

这些扩展程序实际上可能帮助您使用EditorFor。您可以保留EditorFor调用,该调用将为ISettings呈现EditTemplate,并且您将放置扩展方法以针对不同的继承情况提供不同的行为。

另一种方法是简单地使用不同的EditTemplate元素,每个具体类型一个(继承),如果它们彼此差异很大,并使用特定的模板名称调用EditorFor。 / p>

答案 1 :(得分:0)

我很久以前找到了一个解决方案,忘记在这里发帖了...我无法发布我所做的一切,但基本的想法是在ISettings界面添加一个属性,如:

public interface ISettings
{
    string Name { get; }

    string EditorTemplatePath { get; }
}

然后,您需要在每个类中覆盖它。例如:

public class SettingsA : ISettings
{
    public string Name { get { return "Example A"; } }

    public string EditorTemplatePath
    {
        get{ return "~/Views/Shared/EditorTemplates/SettingsA.cshtml"; } 
    }

    public string CustomAttributeA1 { get; set; }

    public string CustomAttributeA2 { get; set; }
}

public class SettingsB : ISettings
{
    public string Name { get { return "Example B"; } }

    public string EditorTemplatePath
    {
        get{ return "~/Views/Shared/EditorTemplates/SettingsB.cshtml"; } 
    }

    public string CustomAttributeB1 { get; set; }

    public string CustomAttributeB2 { get; set; }
}

当然,您需要在某个控制器中实现自己的逻辑以返回自定义HTML。对我来说,我使用AJAX并做这样的事情:

[Route("get-editor-ui/{type}")]
public ActionResult GetEditorUI(string type)
{
    var model = // logic to get the model from "type" argument

    if (model == null)
    {
        return HttpNotFound();
    }

    string content = RenderRazorPartialViewToString(model.EditorTemplatePath, model);
    return Json(new { Content = content }, JsonRequestBehavior.AllowGet);
}

仅供参考,RenderRazorPartialViewToString在我的基本控制器中,定义如下:

public string RenderRazorPartialViewToString(string viewName, object model)
{
    ViewData.Model = model;
    using (var sw = new StringWriter())
    {
        var viewResult = System.Web.Mvc.ViewEngines.Engines.FindPartialView(ControllerContext, viewName);
        var viewContext = new ViewContext(ControllerContext, viewResult.View, ViewData, TempData, sw);
        viewResult.View.Render(viewContext, sw);
        viewResult.ViewEngine.ReleaseView(ControllerContext, viewResult.View);
        return sw.GetStringBuilder().ToString();
    }
}