所以我有一个这样的界面:
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选择器标签..但似乎不是理想的方法。这个问题有一些很好的解决方法吗?处理这种情况的最佳方法是什么?
答案 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();
}
}