ASP.NET MVC剃刀:HTML中的条件属性


83

下面的代码似乎并不干净。有任何改进代码的建议吗?

<li @if(ViewData["pagename"].ToString()=="Business details"){ <text>class="active" </text> } >
        <a  @if(ViewData["pagename"].ToString()=="Business details"){ <text>style="color: white; background-color: #08C; border: 1px solid #08C;" </text> }
            href="@Url.Action("BusinessDetails", "Business")">Business Details</a>
    </li> 
    <li @if (ViewData["pagename"].ToString() == "Booking policies"){ <text>class="active"</text> }> 
        <a  @if (ViewData["pagename"].ToString() == "Booking policies")
               { <text>style="color: white; background-color: #08C; border: 1px solid #08C;" </text> }
            href="@Url.Action("BookingPolicies", "Business")">Booking policies</a> 
    </li> 

也许创建一个自定义HTML帮助器,以使用子链接元素来呈现LI?
尼克·博克

Answers:


142

MVC具有内置的条件属性...

<div @{if (myClass != null) { <text>class="@myClass"</text> } }>Content</div>
<div class="@myClass">Content</div>

如果@myClass为null,则根本不会使用该属性。

我知道这可能无法完全解决您当前的问题,但是值得注意!

http://weblogs.asp.net/jgalloway/archive/2012/02/16/asp-net-4-beta-released.aspx


请注意,您的班级名称未处于“活动状态”,否则您将具有条目班级属性。不知道为什么。
ScottE 2014年

3
调用传递匿名htmlProperties对象的html帮助程序时,是否有办法实现相同的尊重空行为?例如,我想有条件地传递attribute disabled,如@Html.TextBoxFor(lambda, new { disabled = condition ? true : null }),但仍会disabled=""disabledwas时呈现null,这与rendring相同,disabled="anything"因为disabled在存在该属性时该属性处于活动状态,而与值无关。找到关于该主题的stackoverflow.com/q/7978137/11683,但是如今我想知道还有更好的方法吗?
GSerg 2014年

1
附注:“数据-...”属性不能是有条件的,甚至空渲染空值(stackoverflow.com/questions/13267619/...
阿列克谢Levenkov

75
<li class="@(ViewBag.pagename == "Business details" ? "active" : null)">  

您应该style="..."使用单独的类名替换内联,并在其中使用相同的语法。

但是,制作一个单独的HTML帮助程序扩展方法会更干净一些,该方法采用页面和操作名称并通用地生成HTML。


1
不错,比其他一些选项(Razor 2.0选项除外)更干净。
ctrlplusb

21

我使用一个小的辅助方法,如果该值是非空值,并且在定义了布尔函数表达式的结果为时,它将有条件地添加一个属性true

public static MvcHtmlString Attr(this HtmlHelper helper, string name, string value, Func<bool> condition = null)
{
    if (string.IsNullOrEmpty(name) || string.IsNullOrEmpty(value))
    {
        return MvcHtmlString.Empty;
    }

    var render = condition != null ? condition() : true;

    return render ? 
        new MvcHtmlString(string.Format("{0}=\"{1}\"", name, HttpUtility.HtmlAttributeEncode(value))) : 
        MvcHtmlString.Empty;
}

定义后,我可以在Razor视图中使用此方法:

<li @(Html.Attr("class", "new", () => example.isNew))>
...
</li>

上面的代码将渲染<li class="new">...</li>if example.isNew == true,否则将省略整个class属性。


1
这样做非常优雅。但是Func<bool>我会选择一个简单的bool?参数,而不是lambda,因为它更简单:<li @Html.Attr("class", "new", example.isNew)>
T-moty

我喜欢这种方法,因为当属性名称仍然存在时,我的应用程序中的许多自定义JavaScript仍将运行。至少由于属性差异,这不会使您重复相同的div。谢谢!
本·塞沃斯


0

采用TagWrap扩展方法。您问题的代码如下所示:

@using (Html.TagWrap("li", condition ? new { @class = "active" } : null))
{
    var anchorAttrs = new Dictionary<string, object> { { "href", Url.Action("BusinessDetails", "Business") } };
    if(condition)
    {
        anchorAttrs["style"] = "color: white; background-color: #08C; border: 1px solid #08C;";
    }
    using (Html.TagWrap("a", anchorAttrs))
    {
        <text>Business Details</text>
    }
}

TagWrap扩展方法

使用Microsoft.AspNetCore.Mvc.ViewFeatures;

public static IDisposable TagWrap(this IHtmlHelper htmlHelper, string tagName, object data)
{
    return htmlHelper.TagWrap(tagName, HtmlHelper.AnonymousObjectToHtmlAttributes(data));
}

public static IDisposable TagWrap(this IHtmlHelper htmlHelper, string tagName, IDictionary<string, object> data)
{
    var tag = new TagBuilder(tagName);
    tag.MergeAttributes(data);

    htmlHelper.ViewContext.Writer.Write(tag.RenderStartTag());

    return new DisposableAction(() =>
        htmlHelper.ViewContext.Writer.Write(tag.RenderEndTag()));
}

用于在Dispose上呈现结束标记的Helper类

public class DisposableAction : IDisposable
{
    private readonly Action DisposeAction;

    public DisposableAction(Action action)
    {
        DisposeAction = action;
    }

    public void Dispose()
    {
        DisposeAction();
    }
}

0

根据除霜在这里回答一个适应,取一个object代替string

    public static MvcHtmlString ConditionalAttr(this HtmlHelper helper, string attributeName, object value, Func<bool> condition)
    {
        if (string.IsNullOrEmpty(attributeName) || value == null)
        {
            return MvcHtmlString.Empty;
        }

        var render = condition != null ? condition() : true;

        return render ? 
            new MvcHtmlString($"{attributeName}=\"{HttpUtility.HtmlAttributeEncode(value.ToString())}\"") : 
            MvcHtmlString.Empty;
    }

这样,您不必在传递其他数据类型之前将其转换为字符串,从而节省了fiew .ToString()有一个区别:通过传递一个空字符串仍然会渲染。例如:

@Html.ConditionalAttr("data-foo", "", () => Model.IsFooNeeded)

// Ouput:
data-foo=""

0
@{ var classAttr= needClass ? "class=\"class-name\"" : "" }

然后在HTML中

<li @Html.Raw(classAttr) >  
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.