【问题标题】:MVC3 Html.DisplayFor -- Is it possible to have this control generate an ID?MVC3 Html.DisplayFor -- 是否可以让这个控件生成一个 ID?
【发布时间】:2012-10-09 06:19:45
【问题描述】:

我希望能够显示一些文本,但也可以通过 jQuery 修改文本。

<%= Html.DisplayFor(model => model.DeviceComponentName)%>

如果我使用 EditorFor 而不是 DisplayFor,我会看到输入控件的 ID。不过,我不希望以这种方式编辑该值。因此,我将其设为 DisplayFor,但它不会为元素生成 ID 属性。

我是否应该将 DisplayFor 包装在一个 div 中并执行以下操作:

<div id="<%= ViewData.TemplateInfo.GetFullHtmlFieldName("DeviceComponentName") %>">
    <%= Html.DisplayFor(model => model.DeviceComponentName)%>
</div>

$('#DeviceComponentName').text('newValue');

或者有没有更清洁的方法来实现这一点?

更新:有没有不依赖硬编码字符串的方法?与对象本身相关的东西,所以如果我的属性名称发生更改,我会收到编译错误?

另外,我正在使用此代码,但没有看到 ID 值出现:

<td class="editableValue">
    <%--Label should be editable, so it needs an ID, but only will be edited by jQuery so it can't be an EditorFor--%>
    <%= Html.DisplayFor(model => model.DeviceComponentName, new { id = "DeviceComponentName" })%>
    <button type="button" id="ComponentTreeButton" class="nestedDialogButton">...</button>
</td>

【问题讨论】:

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


    【解决方案1】:

    为避免“魔术字符串”输入(以防您的模型属性发生变化),您可以通过扩展来做到这一点。它还使代码更简洁:

    public static MvcHtmlString DisplayWithIdFor<TModel, TValue>(this HtmlHelper<TModel> helper, Expression<Func<TModel, TValue>> expression, string wrapperTag = "div")
    {
        var id = helper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldId(ExpressionHelper.GetExpressionText(expression));
        return MvcHtmlString.Create(string.Format("<{0} id=\"{1}\">{2}</{0}>", wrapperTag, id, helper.DisplayFor(expression)));
    }
    

    然后像这样简单地使用它:

    @Html.DisplayWithIdFor(x => x.Name)
    

    会产生

    <div id="Name">Bill</div>
    

    或者如果你希望它被包裹在一个跨度中:

    @Html.DisplayWithIdFor(x => x.Name, "span")
    

    这将使:

    <span id="Name">Bill</span>
    

    非剃须刀

    对于非 Razor 语法,您只需像这样使用它:

    <%= Html.DisplayWithIdFor(x => x.Name) %>
    

    和:

    <%= Html.DisplayWithIdFor(x => x.Name, "span") %>
    

    【讨论】:

    • 非剃刀语法是否应该在 Html 之前有 @?
    【解决方案2】:

    你必须使用:

    Html.DisplayFor(model => model.DeviceComponentName, new { @id = "DeviceComponentName"})
    

    对于动态 id 和其他属性,我使用:

    元数据类:

    public class AdditionalHtml : Attribute, IMetadataAware
    {
        public string Id { get; set; }
    
        public string Type { get; set; }
    
        public string CssClass { get; set; }
    
        public string PlaceHolder { get; set; }
    
        public string Style { get; set; }
    
        public string OnChange { get; set; }
    
        public int Rows { get; set; }
    
        public int MaxLength { get; set; }
    
        public bool ReadOnly { get; set; }
    
        public bool Disabled { get; set; }
    
        public Dictionary<string, object> OptionalAttributes ()
        {
            var options = new Dictionary<string, object>();
    
            if ( !string.IsNullOrWhiteSpace( Id ) )
                options.Add( "id", Id );
    
            if ( !string.IsNullOrWhiteSpace( Type ) )
                options.Add( "type", Type );
    
            if ( !string.IsNullOrWhiteSpace( CssClass ) )
                options.Add( "class", CssClass );
    
            if ( !string.IsNullOrWhiteSpace( PlaceHolder ) )
                options.Add( "placeholder", PlaceHolder );
    
            if ( !string.IsNullOrWhiteSpace( OnChange ) )
                options.Add( "onchange", OnChange );
    
            if ( !string.IsNullOrWhiteSpace( Style ) )
                options.Add( "style", Style );
    
            if ( Rows != 0 )
                options.Add( "rows", Rows );
    
            if ( MaxLength != 0 )
                options.Add( "maxlength", MaxLength );
    
            if ( ReadOnly )
                options.Add( "readonly", "readonly" );
    
            if ( Disabled )
                options.Add( "disabled", "disabled" );
    
            return options;
        }
    

    元数据提供者的类:

    public class MetadataProvider : DataAnnotationsModelMetadataProvider
    {
        protected override ModelMetadata CreateMetadata ( IEnumerable<Attribute> attributes, Type containerType, Func<object> modelAccessor, Type modelType, string propertyName )
        {
            var metadata = base.CreateMetadata( attributes, containerType, modelAccessor, modelType, propertyName );
    
            var additionalHtmlValues = attributes.OfType<AdditionalHtml>().FirstOrDefault();
    
            if ( additionalHtmlValues != null )
            {
                metadata.AdditionalValues.Add( "AdditionalHtml", additionalHtmlValues );
            }
    
            return metadata;
        }
    }
    

    添加助手:

    public static class HtmlAttributesHelper
    {
        public static string GetHtmlAttribute<T> ( this T model, Expression<Func<T, object>> expression, string attribName )
        {
            string strDefault = String.Empty;
            MemberInfo member = null;
    
            switch ( expression.Body.NodeType )
            {
                case ExpressionType.Lambda:
                case ExpressionType.Convert:
                    {
                        var body = expression.Body as UnaryExpression;
                        if ( body == null )
                            return strDefault;
                        var operand = body.Operand as MemberExpression;
                        if ( operand == null )
                            return strDefault;
                        member = operand.Member;
                        break;
                    }
                case ExpressionType.MemberAccess:
                    {
                        var body = expression.Body as MemberExpression;
                        if ( body == null )
                            return strDefault;
                        member = body.Member;
                        break;
                    }
                default:
                    {
                        return expression.Body.ToString() + " " + expression.Body.NodeType.ToString();
                    }
            }
    
            if ( member == null )
                return strDefault;
    
            var attr = member.GetCustomAttributes( typeof( AdditionalHtml ), false );
            if ( attr.Length > 0 )
            {
                return ( attr [ 0 ] as AdditionalHtml ).OptionalAttributes() [ attribName.ToLower() ].ToString();
            }
    
            // Return Name of Property if AdditionalHtml.Id is empty
            return attribName == "Id" ? member.Name : strDefault;
        }
    
        public static string GetHtmlId<T> ( this T model, Expression<Func<T, object>> expression )
        {
            return model.GetHtmlAttribute( expression, "Id" );
        }
    }
    

    在 Global.asax 中注册提供商:

    protected void Application_Start ()
        {
            AreaRegistration.RegisterAllAreas();
    
            //....
            ModelMetadataProviders.Current = new MetadataProvider();
        }
    

    在您的模型中,您可以像这样使用 AdditionHtml:

    [AdditionalHtml( Id = "OrderNo", CssClass = ShortTextStyle, Disabled = true )]
        public string OrderNo { get; set; }
    

    现在你可以对 js 使用 sintax(在视图中):

    $('#@Model.GetHtmlId( x => x.PropertyName)')
    

    在视图中,您可以使用:

    @Html.DisplayFor( x => x.FormDate )
    

    自动附加 HTML 属性

    【讨论】:

    • 有没有办法让它成为动态的?如果我的住宿名称发生变化怎么办?
    • @SeanAnderson 是的,您可以使用 ViewBag 或 ViewData 从控制器 @Html.DisplayFor(model =&gt; model.DeviceComponentName, new { id = ViewBag.DeviceComponentID }) 传递 id 值
    【解决方案3】:

    只需在列上方添加一个 HiddenFor。这将为您提供一个 ID 用于您需要的东西。很简单,您可以通过 ID 获取该值。

    <%= Html.HiddenFor(model => model.DeviceComponentName)%>
    <%= Html.DisplayFor(model => model.DeviceComponentName)%>
    

    【讨论】:

      【解决方案4】:

      HtmlHelpers 具有允许您传入对象或字典的覆盖,以将属性添加到生成的 html 标记:

      @Html.DisplayFor(model => model.DeviceComponentName, new { id = "myId" })
      
      @Html.DisplayFor(model => model.DeviceComponentName, new Dictionary<string, object>() { { "id", "myId" } })
      

      @Html.DisplayFor(model => model.DeviceComponentName, new { id = ViewData.TemplateInfo.GetFullHtmlFieldName("DeviceComponentName") })
      
      @Html.DisplayFor(model => model.DeviceComponentName, new Dictionary<string, object>() { { "id", ViewData.TemplateInfo.GetFullHtmlFieldName("DeviceComponentName" } })
      

      更新:

      在查看更新的代码并重新阅读问题后,这是我的建议 - 这与您的第一个想法相似。

      <td class="editableValue" id="<%= ViewData.TemplateInfo.GetFullHtmlFieldName("DeviceComponentName") %>">
        <%= Html.DisplayFor(model => model.DeviceComponentName)%>
        <button type="button" id="ComponentTreeButton" class="nestedDialogButton">...</button>
      </td>
      

      您不需要在 TD 中添加额外的 div,因为您可以直接通过 jQuery 修改 td 中的值。我相信以下应该做到这一点:

      $('#DeviceComponentName').html('newValue');
      

      【讨论】:

      • 我没有使用 Razor 语法,但是当我使用任何一个示例时,我都没有看到 ID 出现。我会将我尝试过的内容编辑到顶部帖子中。
      【解决方案5】:

      我们无法在 razor 中为 Displayfor() 控件创建 id。我们可以使用像 span 标签这样的 html 控件来代替 Displayfor() 控件。其他明智的我们可以将 displayfor control 放在 span control 中。现在我们可以为 span 创建 id 了。我们必须这样做..

      示例&lt;span id="spanid"&gt;@Html.Displayfor(modelItem =&gt; item.id) &lt;/span&gt;

      【讨论】:

        【解决方案6】:

        这是具有添加 htmlAttributes 能力的 naspinski 解决方案。

            public static MvcHtmlString DisplayWithIdFor<TModel, TValue>(this HtmlHelper<TModel> helper, Expression<Func<TModel, TValue>> expression, object htmlAttributes, string wrapperTag = "div")
            {
                var id = helper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldId(ExpressionHelper.GetExpressionText(expression));
        
                if (htmlAttributes != null)
                {
                    var tag = new TagBuilder(wrapperTag);
                    tag.MergeAttributes(HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes) as IDictionary<string, object>);
                    tag.Attributes.Add("id", id);
                    tag.SetInnerText(helper.DisplayFor(expression).ToHtmlString());
        
                    return MvcHtmlString.Create(tag.ToString(TagRenderMode.Normal));
                }
                else
                {
                    return MvcHtmlString.Create(string.Format("<{0} id=\"{1}\">{2}</{0}>", wrapperTag, id, helper.DisplayFor(expression)));
                }
            }
        

        【讨论】:

          【解决方案7】:

          对我来说最简单的解决方案是使用只读文本框。 @Html.TextBoxFor(u => u.Visibilidade, new { disabled = "disabled" })

          【讨论】:

            猜你喜欢
            • 2019-12-15
            • 2015-02-01
            • 1970-01-01
            • 1970-01-01
            • 2019-11-05
            • 2011-08-08
            • 2021-03-23
            • 1970-01-01
            • 2019-08-24
            相关资源
            最近更新 更多