42

より少ないコード行 (おそらく 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>
4

8 に答える 8

56

ASP.NET MVC 4 で修正済み

http://weblogs.asp.net/jgalloway/archive/2012/02/16/asp-net-4-beta-released.aspxを参照してください。

条件付き属性のレンダリング

null の可能性がある属性がある場合、以前は、次のように空の属性を書き出さないように null チェックを行う必要がありました。

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

Razor はそれを自動的に処理できるようになったので、属性を書き出すだけで済みます。null の場合、属性は書き込まれません。

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

したがって、@myClass が null の場合、出力は次のようになります。

<div>Content</div>
于 2012-03-01T21:29:20.710 に答える
41

以下の Razor 構文を使用できるように、連鎖可能な HtmlAttribute クラスといくつかの Html 拡張メソッドを考え出しました。

<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 拡張ヘルパー メソッドは次のとおりです。

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);
    }
}

それらが役に立つかどうか教えてください。

ありがとう、

リー

于 2010-11-20T12:08:59.733 に答える
11
<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>

テストはしていませんが、正しく解析されます。

于 2010-09-27T01:50:49.037 に答える
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>
于 2010-09-27T06:27:08.910 に答える
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>
于 2011-03-30T19:02:37.710 に答える
1

複数のクラスの場合、次の単純な拡張メソッドを使用します。

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

そしてビューで:

<div class="menuitem @("active".If(Model.Active))">
于 2014-11-12T14:05:05.443 に答える
-1

それは本当にとてもシンプルできれいです:

<p @(cssClass != null) ? { class="@cssClass" }> Stuff and whatnot... </p>
于 2011-04-21T18:17:59.020 に答える