在 MVC 中处理动态 HTML 类 的优雅方法
Elegant approach to handle dynamic HTML classes in MVC
我有一个自定义 MVC HTML Helper 方法,如下所示:
public static MvcHtmlString Div (this HtmlHelper htmlHelper,
VehicleStatusViewModel vehicleStatus, string classType)
我调用此辅助方法来帮助我选择正确的 bootstrap class 以用于我认为的 div。在该方法内部,我使用一个开关来遍历 vehicleStatus 的可能状态并分配相应的 bootstrap class。 IE。如果 vehicleStatus = 1,面板面板成功,如果 vehicleStatus = 2,面板面板危险。
但是,我可能想再次根据 VehicleStatus 的特定 returned 状态分配一个特定的字形图标。将来,我可能会有更多 class 类型。
在我看来,当我调用这个 Helper 方法时,我想传递一个 classType(即面板或字形图标)。在我的 Helper 方法中,无需为每种可能的 class 类型复制我的开关代码,我想要一个 优雅的解决方案来呈现特定的 classType 我的视图 正在请求并且 return 具有适当分配的 class/class-type 的 TagBuilder div,这样:
@Html.Div(vehicleStatus, "panel")
// Would resolve and return, if vehicleStatus was 1:
<div class="panel panel-success"> </div>
// Calling the same method, vehicleStatus = 1 but expecting a respective
// glyphicon:
@Html.Div(vehicleStatus, "glyphicon")
<div class="glyphicon glyphicon-remove-circle"> </div>
好吧,您对问题的描述听起来像是基本 class 或接口设置的完美示例(将来有可能通过覆盖base class and/or 以不同方式实现接口)。
这可能是您要找的,也可能不是。我以前使用过类似的模式,通常是在域中,但有时用于 Razor 目的。在这种情况下,可以使用基数 class。完成后,我意识到我稍微过度设计了这个例子。您可能可以轻松地完成 2 个级别,直到达到您想要的级别。
public abstract class HtmlTag
{
private readonly String _tag;
//allow different type of tags to be rendered
protected HtmlTag(String tag)
{
if (String.IsNullOrWhiteSpace(tag))
throw new ArgumentException("Value cannot be null or whitespace.", "tag");
_tag = tag;
}
//require a VehicleStatus for rendering to an HtmlString
public String ToHtmlString( VehicleStatus vehicleStatus )
{
var tag = new TagBuilder( _tag );
this.CreateTag( tag, vehicleStatus );
return tag.ToString();
}
//require subclasses to implement the CreateTag method
//this method will allow subclasses to modify the tag builder as needed
//depending on the vehicle status
protected abstract void CreateTag( TagBuilder tagBuilder, VehicleStatus vehicleStatus );
}
然后,如果您特别想要 div
或 span
,例如:
public abstract class Div : HtmlTag
{
protected Div( )
: base( "div" )
{
}
}
public abstract class Span : HtmlTag
{
protected Span()
: base("span")
{
}
}
最后,您需要做的就是创建 classes 来实现 CreateTag 方法:
public class PanelDiv : Div
{
protected override void CreateTag( TagBuilder tagBuilder, VehicleStatus vehicleStatus )
{
tagBuilder.AddCssClass( "panel" );
tagBuilder.AddCssClass(vehicleStatus == VehicleStatus.Success
? "panel-success"
: "panel-danger");
}
}
public class GlyphiconDiv : Div
{
protected override void CreateTag( TagBuilder tagBuilder, VehicleStatus vehicleStatus )
{
tagBuilder.AddCssClass( "glyphicon" );
tagBuilder.AddCssClass( vehicleStatus == VehicleStatus.Success
? "glyphicon-remove-circle"
: "glyphicon-add-circle" );
}
}
如果您想添加另一种类型,您需要做的就是:
public class MyOtherDiv : Div
{
protected override void CreateTag( TagBuilder tagBuilder, VehicleStatus vehicleStatus )
{
//adjust the tag here based on vehicle status
}
}
最后,您的 HtmlHelper:
public static class DivHtmlHelperExtensions
{
public static IHtmlString Div( this HtmlHelper htmlHelper, VehicleStatus vehicleStatus, HtmlTag htmlTag )
{
//simply return the HtmlString representation of your HtmlTag you passed in
return new HtmlString( htmlTag.ToHtmlString( vehicleStatus ) );
}
//call this method likeso (from a view):
//@Html.Div(vehicleStatus, new PanelDiv());
//@Html.Div(vehicleStatus, new GlyphiconDiv());
}
如果您发现自己一遍又一遍地执行相同的条件,您可以稍微重构父级 class 以处理更多责任:
public abstract class Div : HtmlTag
{
private readonly String _className;
private readonly String _trueCssClass;
private readonly String _falseCssClass;
protected Div( String className, String trueCssClass, String falseCssClass )
: base( "div" )
{
_className = className;
_trueCssClass = trueCssClass;
_falseCssClass = falseCssClass;
}
//the div will use the constructing parameters to populate the classes instead
protected override void CreateTag( TagBuilder tagBuilder, VehicleStatus vehicleStatus )
{
tagBuilder.AddCssClass( _className );
tagBuilder.AddCssClass( vehicleStatus == VehicleStatus.Success
? _trueCssClass
: _falseCssClass );
}
}
//and your subclass:
public class PanelDiv : Div
{
public PanelDiv()
: base( "panel", "panel-success", "panel-danger" )
{
}
}
如果这不是您想要的,请告诉我。
我有一个自定义 MVC HTML Helper 方法,如下所示:
public static MvcHtmlString Div (this HtmlHelper htmlHelper,
VehicleStatusViewModel vehicleStatus, string classType)
我调用此辅助方法来帮助我选择正确的 bootstrap class 以用于我认为的 div。在该方法内部,我使用一个开关来遍历 vehicleStatus 的可能状态并分配相应的 bootstrap class。 IE。如果 vehicleStatus = 1,面板面板成功,如果 vehicleStatus = 2,面板面板危险。
但是,我可能想再次根据 VehicleStatus 的特定 returned 状态分配一个特定的字形图标。将来,我可能会有更多 class 类型。
在我看来,当我调用这个 Helper 方法时,我想传递一个 classType(即面板或字形图标)。在我的 Helper 方法中,无需为每种可能的 class 类型复制我的开关代码,我想要一个 优雅的解决方案来呈现特定的 classType 我的视图 正在请求并且 return 具有适当分配的 class/class-type 的 TagBuilder div,这样:
@Html.Div(vehicleStatus, "panel")
// Would resolve and return, if vehicleStatus was 1:
<div class="panel panel-success"> </div>
// Calling the same method, vehicleStatus = 1 but expecting a respective
// glyphicon:
@Html.Div(vehicleStatus, "glyphicon")
<div class="glyphicon glyphicon-remove-circle"> </div>
好吧,您对问题的描述听起来像是基本 class 或接口设置的完美示例(将来有可能通过覆盖base class and/or 以不同方式实现接口)。
这可能是您要找的,也可能不是。我以前使用过类似的模式,通常是在域中,但有时用于 Razor 目的。在这种情况下,可以使用基数 class。完成后,我意识到我稍微过度设计了这个例子。您可能可以轻松地完成 2 个级别,直到达到您想要的级别。
public abstract class HtmlTag
{
private readonly String _tag;
//allow different type of tags to be rendered
protected HtmlTag(String tag)
{
if (String.IsNullOrWhiteSpace(tag))
throw new ArgumentException("Value cannot be null or whitespace.", "tag");
_tag = tag;
}
//require a VehicleStatus for rendering to an HtmlString
public String ToHtmlString( VehicleStatus vehicleStatus )
{
var tag = new TagBuilder( _tag );
this.CreateTag( tag, vehicleStatus );
return tag.ToString();
}
//require subclasses to implement the CreateTag method
//this method will allow subclasses to modify the tag builder as needed
//depending on the vehicle status
protected abstract void CreateTag( TagBuilder tagBuilder, VehicleStatus vehicleStatus );
}
然后,如果您特别想要 div
或 span
,例如:
public abstract class Div : HtmlTag
{
protected Div( )
: base( "div" )
{
}
}
public abstract class Span : HtmlTag
{
protected Span()
: base("span")
{
}
}
最后,您需要做的就是创建 classes 来实现 CreateTag 方法:
public class PanelDiv : Div
{
protected override void CreateTag( TagBuilder tagBuilder, VehicleStatus vehicleStatus )
{
tagBuilder.AddCssClass( "panel" );
tagBuilder.AddCssClass(vehicleStatus == VehicleStatus.Success
? "panel-success"
: "panel-danger");
}
}
public class GlyphiconDiv : Div
{
protected override void CreateTag( TagBuilder tagBuilder, VehicleStatus vehicleStatus )
{
tagBuilder.AddCssClass( "glyphicon" );
tagBuilder.AddCssClass( vehicleStatus == VehicleStatus.Success
? "glyphicon-remove-circle"
: "glyphicon-add-circle" );
}
}
如果您想添加另一种类型,您需要做的就是:
public class MyOtherDiv : Div
{
protected override void CreateTag( TagBuilder tagBuilder, VehicleStatus vehicleStatus )
{
//adjust the tag here based on vehicle status
}
}
最后,您的 HtmlHelper:
public static class DivHtmlHelperExtensions
{
public static IHtmlString Div( this HtmlHelper htmlHelper, VehicleStatus vehicleStatus, HtmlTag htmlTag )
{
//simply return the HtmlString representation of your HtmlTag you passed in
return new HtmlString( htmlTag.ToHtmlString( vehicleStatus ) );
}
//call this method likeso (from a view):
//@Html.Div(vehicleStatus, new PanelDiv());
//@Html.Div(vehicleStatus, new GlyphiconDiv());
}
如果您发现自己一遍又一遍地执行相同的条件,您可以稍微重构父级 class 以处理更多责任:
public abstract class Div : HtmlTag
{
private readonly String _className;
private readonly String _trueCssClass;
private readonly String _falseCssClass;
protected Div( String className, String trueCssClass, String falseCssClass )
: base( "div" )
{
_className = className;
_trueCssClass = trueCssClass;
_falseCssClass = falseCssClass;
}
//the div will use the constructing parameters to populate the classes instead
protected override void CreateTag( TagBuilder tagBuilder, VehicleStatus vehicleStatus )
{
tagBuilder.AddCssClass( _className );
tagBuilder.AddCssClass( vehicleStatus == VehicleStatus.Success
? _trueCssClass
: _falseCssClass );
}
}
//and your subclass:
public class PanelDiv : Div
{
public PanelDiv()
: base( "panel", "panel-success", "panel-danger" )
{
}
}
如果这不是您想要的,请告诉我。