【问题标题】:ASP.NET MVC razor: conditional attribute in HTMLASP.NET MVC razor:HTML 中的条件属性
【发布时间】:2012-03-13 01:26:56
【问题描述】:

下面的代码看起来不太干净。 有什么改进代码的建议吗?

<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?

标签: asp.net-mvc asp.net-mvc-3 razor


【解决方案1】:
<li class="@(ViewBag.pagename == "Business details" ? "active" : null)">  

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

但是,创建一个单独的 HTML 帮助程序扩展方法会更简洁,该方法采用页面和操作名称并通用生成 HTML。

【讨论】:

  • 不错,比其他一些选项(除了 Razor 2.0 选项)干净得多。
【解决方案2】:

MVC 内置了条件属性...

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

如果@myClass 为空,它根本不会使用该属性...

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

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

【讨论】:

  • 注意你的类名不是“活动的”,否则你会有一个入口类属性。不知道为什么。
  • 在调用传递匿名 htmlProperties 对象的 html 助手时,有没有办法实现同样的 null 尊重行为?例如。我想有条件地传递属性disabled,比如@Html.TextBoxFor(lambda, new { disabled = condition ? true : null }),但是当disabled 是null 时仍然呈现disabled="",这与呈现disabled="anything" 相同,因为disabled 在属性为时处于活动状态存在,无论价值如何。在该主题上找到stackoverflow.com/q/7978137/11683,但我想知道现在有更好的方法吗?
  • 旁注:“data-...”属性不能是有条件的,即使为 null (stackoverflow.com/questions/13267619/…) 也不能呈现空值
  • 该死!直到现在才知道这个:-)
  • @GSerg 尝试使用@Html.TextBoxFor(lambda, condition ? new { disabled = true } : null);这就是我通常为 HTML Helpers 所做的事情。需要注意的是,我认为它必须是一个对象或 null 才能工作(即,您不能使用两个匿名对象,一个属性被删除作为一个结果)。
【解决方案3】:

在 MVC4 中

<!DOCTYPE html>
<html>
<head>
</head>
<body>
    @{
        string css = "myDiv";
    }
    <div class='@css'></div>
</body>
</html>

或

<!DOCTYPE html>
<html>
<head>
</head>
<body>
    @{
        string css = "class=myDiv";
    }
    <div @css></div>
</body>
</html>

更多信息在这里:http://evolpin.wordpress.com/2012/05/20/mvc-4-code-enhancements/

【讨论】:

    【解决方案4】:

    我使用一个小的帮助方法,如果值非空,并且如果定义了,当布尔函数表达式的计算结果为 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>
    

    如果example.isNew == true,上述代码将呈现&lt;li class="new"&gt;...&lt;/li&gt;,否则将省略整个class属性。

    【讨论】:

    • 非常优雅的方式来做到这一点。但比起Func&lt;bool&gt; lambda,我更喜欢简单的bool? 参数,因为它更简单:&lt;li @Html.Attr("class", "new", example.isNew)&gt;
    • 我喜欢这种方法,因为当属性名称仍然存在时,我的应用程序中的许多自定义 JavaScript 仍将运行。而且至少这不会让你因为属性差异而重复相同的 div。谢谢!
    【解决方案5】:

    使用 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 上呈现结束标记的助手类

    public class DisposableAction : IDisposable
    {
        private readonly Action DisposeAction;
    
        public DisposableAction(Action action)
        {
            DisposeAction = action;
        }
    
        public void Dispose()
        {
            DisposeAction();
        }
    }
    

    【讨论】:

      【解决方案6】:

      这里根据除霜答案进行了改编,采用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;
          }
      

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

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

      【讨论】:

        【解决方案7】:
        @{ var classAttr= needClass ? "class=\"class-name\"" : "" }
        

        然后在 HTML 中

        <li @Html.Raw(classAttr) >  
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2010-09-15
          • 2012-05-15
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-04-30
          相关资源
          最近更新 更多