如何使用剃刀视图引擎简洁地创建可选的HTML属性?

时间:2010-09-27 00:45:56

标签: asp.net-mvc razor viewengine

我正在寻找一种用较少的代码行编写以下代码的方法(可能是5)。我想我可以做与所选类相同的事情,但这种剃刀语法看起来并不漂亮。

<ul>
@foreach (var mi in Model.MenuItems) {
  <li@(mi.Selected?" class=\"selected\"":null)>
  @if (string.IsNullOrEmpty(mi.Title)) {
    <a href="@mi.Href">@mi.Text</a>
  } else {
    <a href="@mi.Href" title="@mi.Title">@mi.Text</a>
  }
  </li>
}
</ul>

8 个答案:

答案 0 :(得分:51)

已在ASP.NET MVC 4中修复

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

条件属性渲染

如果你的属性可能为null,那么在过去你需要进行空检查以避免写出空属性,如下所示:

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

现在Razor能够自动处理,所以你可以写出属性。如果为null,则不写入该属性:

<div class="@myClass">Content</div>

因此,如果@myClass为null,则输出就是:

<div>Content</div>

答案 1 :(得分:41)

我想出了一个可链接的HtmlAttribute类和一些Html扩展方法,以允许下面的Razor语法:

<ul> 
    @foreach (var mi in items) { 
    <li @Html.Css("selected", mi.Selected)> 
        <a href="@mi.Href" @Html.Attr("title", mi.Title)>@mi.Text</a> 
    </li> 
    } 
</ul> 

这是HtmlAttribute类:

public class HtmlAttribute : IHtmlString     
{
    private string _InternalValue = String.Empty;
    private string _Seperator;

    public string Name { get; set; }
    public string Value { get; set; }
    public bool Condition { get; set; }

    public HtmlAttribute(string name)
        : this(name, null)
    {
    }

    public HtmlAttribute( string name, string seperator )
    {
        Name = name;
        _Seperator = seperator ?? " ";
    }

    public HtmlAttribute Add(string value)
    {
        return Add(value, true);
    }

    public HtmlAttribute Add(string value, bool condition)
    {
        if (!String.IsNullOrWhiteSpace(value) && condition)
            _InternalValue += value + _Seperator;

        return this;
    }

    public string ToHtmlString()
    {
        if (!String.IsNullOrWhiteSpace(_InternalValue))
            _InternalValue = String.Format("{0}=\"{1}\"", Name, _InternalValue.Substring(0, _InternalValue.Length - _Seperator.Length));
        return _InternalValue;
    }
}

额外信息:“分隔符”用于将属性的多个值链接在一起。这对于多个css类名(使用空格)或者使用String.Empty构建依赖于多个条件的值(通过使用.Add()方法)非常有用

以下是Html Extension辅助方法:

public static class Extensions
{
    public static HtmlAttribute Css(this HtmlHelper html, string value)
    {
        return Css(html, value, true);
    }

    public static HtmlAttribute Css(this HtmlHelper html, string value, bool condition)
    {
        return Css(html, null, value, condition);
    }

    public static HtmlAttribute Css(this HtmlHelper html, string seperator, string value, bool condition)
    {
        return new HtmlAttribute("class", seperator).Add(value, condition);
    }

    public static HtmlAttribute Attr(this HtmlHelper html, string name, string value)
    {
        return Attr(html, name, value, true);
    }

    public static HtmlAttribute Attr(this HtmlHelper html, string name, string value, bool condition)
    {
        return Attr(html, name, null, value, condition);
    }

    public static HtmlAttribute Attr(this HtmlHelper html, string name, string seperator, string value, bool condition)
    {
        return new HtmlAttribute(name, seperator).Add(value, condition);
    }
}

让我知道它们是否有用。

谢谢,

答案 2 :(得分:10)

<ul>
@foreach (var mi in Model.MenuItems) {
    <li@(mi.Selected?" class=\"selected\"":null)>
        <a href="@mi.Href" @{if(!string.IsNullOrEmpty(mi.Title)) { <text>title="@mi.Title"</text>} }>@mi.Text</a>
    </li>
}
</ul>

我没有测试过,但它正确解析。

答案 3 :(得分:7)

这将是自定义HTML助手的理想选择:

public static class HtmlExtensions
{
    public static MvcHtmlString MenuItem(this HtmlHelper htmlHelper, MenuItem mi)
    {
        var li = new TagBuilder("li");
        if (mi.Selected)
        {
            li.AddCssClass("selected");
        }
        var a = new TagBuilder("a");
        a.MergeAttribute("href", mi.Href);
        if (!string.IsNullOrEmpty(mi.Title))
        {
            a.MergeAttribute("title", mi.Title);
        }
        a.SetInnerText(mi.Text);
        return MvcHtmlString.Create(li.ToString());
    }
}

并在您看来:

<ul>
@foreach (var mi in Model.MenuItems) {
    @Html.MenuItem(mi)
}
</ul>

或使用DisplayTemplates甚至不需要编写循环:

<ul>
    @Html.DisplayFor(x => x.MenuItems)
</ul>

答案 4 :(得分:4)

<ul>
@foreach (var mi in Model.MenuItems) {
  <li@(Html.Raw((mi.Selected ? " class=\"selected\"" : null))>
    <a href="@mi.Href">@mi.Text</a>
  </li>
}
</ul>

答案 5 :(得分:3)

如果值为class

,则Razor不会呈现

null属性

<a href="#nolink" class="@(categoryId == null ? "submenu-active": null)">All</a>

答案 6 :(得分:1)

对于多个类的情况,我使用这个简单的扩展方法:

public static MvcHtmlString If(this string text, bool condition) {
    return new MvcHtmlString(condition ? text : string.Empty);
}

在视图中:

<div class="menuitem @("active".If(Model.Active))">

答案 7 :(得分:-1)

这真的很简单干净:

<p @(cssClass != null) ? { class="@cssClass" }> Stuff and whatnot... </p>
相关问题