Html.TextBox在ASP.NET MVC Preview 5中的条件属性

30

我有一个强类型的MVC视图控件,负责用户创建和编辑客户项目的界面。我希望他们能够在创建时定义ClientId,但不能编辑,并且要在界面中反映出来。

为此,我有以下代码:

<%= Html.TextBox("Client.ClientId", ViewData.Model.ClientId, new 
 { @readonly = 
   (ViewData.Model.ClientId != null && ViewData.Model.ClientId.Length > 0 
      ? "readonly" : "false") 
 } )
%>

似乎无论我给readonly属性赋的值是什么(甚至是"false"和""),Firefox和IE7都会使输入框变为只读,这非常令人不爽且反直觉。是否有一种漂亮的三元操作符方式,在不需要该属性时完全删除它?

8个回答

38

这是一个棘手的问题...不过,如果你只想定义readonly属性,可以这样做:

<%= Html.TextBox("Client.ClientId", ViewData.Model.ClientId, 
  ViewData.Model.ClientId != null && ViewData.Model.ClientId.Length > 0 
    ? new { @readonly =  "readonly" } 
    : null) 
%>

如果您想定义更多的属性,那么您必须定义两种匿名类型并具有多个属性副本。例如,类似于以下内容(我无论如何都不喜欢):

ClientId.Length > 0 
  ? (object)new { @readonly = "readonly", @class = "myCSS" } 
  : (object)new { @class = "myCSS" }

1
我的第一次尝试是第二个代码片段,没有将其转换为对象。这很容易被忽视,但确实是必要的。 - Mathias F

33
如果你想要定义多个属性,并且有条件地将其设置为只读,而不复制其他属性,你可以使用字典来代替匿名类型进行属性定义。
例如:
Dictionary<string, object> htmlAttributes = new Dictionary<string, object>();
htmlAttributes.Add("class", "myCSS");
htmlAttributes.Add("data-attr1", "val1");
htmlAttributes.Add("data-attr2", "val2");
if (Model.LoggedInData.IsAdmin == false)
{
    htmlAttributes.Add("readonly", "readonly");
}


@:User: @Html.TextBoxFor(
    m => m.User,
    htmlAttributes)  

1
应该是答案,因为它避免了重复。 - Ian Warburton

5
提示: 在浏览器中,只要存在readonly / disabled属性,即可将元素设置为只读或禁用。
@Html.TextBoxFor(x => x.Name, isReadonly ?(object) new { @readonly = true } : new { /*Some other attributes*/ })

为什么匿名类需要转换为对象以满足三元操作的第一个条件?并不是挑战它,只是想理解它。谢谢! - eaglei22

4

另一种选择是将其作为普通的HTML发出。是的,编辑器会让你觉得你错了,但这似乎在VS2008SP1中经常发生。此示例特别针对复选框,而在CTP5中似乎完全浪费,但它可以让您了解如何发出有条件的属性。

<input type="checkbox" name="roles" value='<%# Eval("Name") %>' 
  <%# ((bool) Eval("InRole")) ? "checked" : "" %> 
  <%# ViewData.Model.IsInRole("Admin") ? "" : "disabled" %> />

1

我认为应该是这样的

<%= ((bool) Eval("InRole")) ? "checked" : "" %> 

不要像leppies的答案那样。

<%# ((bool) Eval("InRole")) ? "checked" : "" %> 

至少对我来说,使用#没有起作用,但使用=可以。我做错了什么吗?无论如何,感谢您的提示 :)


1
我使用这个:
   @Html.TextAreaFor(model => model.ComentarioGestor, comentarioGestor? new { @class = "form-control" } : new { @class = "form-control", @readonly = "readonly" } as object)

0
$(function() { $("[readonly='false']").removeAttr("readonly"); });
注:该文本为程序相关内容,仅供技术翻译使用。

-1

我尝试了上面大部分的建议,现在我找到了最简单的方法,只需要一行代码。通过将其中一个匿名HTML属性对象声明为“object”类型,将两个匿名HTML属性对象合并。

@Html.TextBoxFor(m => m.Email, !isEdit ? new { id = "email_box" } : new { id = "email_box", @readonly = isEdit ? "readonly" : "false" } as object)

1
这对我不起作用;@readonly = false仍然被解释为readonly - Manuel Reis

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接