MVC 3: 使用 HtmlHelpers 有条件地添加 Disable 属性

我有一个 ASP.Net MVC 3 web 应用程序,我正在使用 HtmlHelper 类为一个视图页面添加一个复选框,像这样..。

@Html.CheckBox("CheckBox1", true, new { @class = "Class1" })

我想做的是根据视图状态属性有条件地添加禁用属性。基本上,以下是最理想的..。

@Html.CheckBox("CheckBox1", true, new { @class = "Class1", @disabled = Model.ReadOnly })

不幸的是,由于禁用属性的性质,这将不起作用,因为分配给禁用属性的 任何值(甚至“ false”)将被转换为 true。

我已经想出了一些解决这个问题的办法,所以问题不是我如何才能做到这一点。但是,是否有一种类似上述所需方法的简单方法?或者我必须采取以下措施之一?..

我知道我能做什么。

  1. 创建一个 if/else 语句,然后写入不同的 Html.CheckBox行(这对可读性不是很好——可能会抛出一个标记警告——不确定)

  2. 跳过 HtmlHelper 类,手动编写标记,从而实现更好的条件属性(使代码更短,但增加了不一致性)

  3. 创建一个自定义助手,它接受一个“禁用”参数(最干净的解决方案,但需要不想要的额外方法-可能是目前为止最好的选择)

53056 次浏览

在您的视图/帮助程序中的某个位置定义它

@functions {
object getHtmlAttributes (bool ReadOnly, string CssClass)
{
if (ReadOnly) {
return new { @class = CssClass, @readonly = "readonly" };
}
return new { @class = CssClass };
}
}

然后使用:

@Html.TextBox("name", "value", @getHtmlAttributes(Model.ReadOnly, "test"))

以下是我对这个类似问题的回答: https://stackoverflow.com/a/13922813/495000


我创建了以下 Helper-它需要一个布尔值和一个匿名对象。如果 Disable 为 true,它将使用值“ disable”向匿名对象(实际上是 Dictionary)添加 Disable 属性,否则它根本不会添加该属性。

public static RouteValueDictionary ConditionalDisable(
bool disabled,
object htmlAttributes = null)
{
var dictionary = HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes);


if (disabled)
dictionary.Add("disabled", "disabled");


return dictionary;
}

这方面的一个实例是:

@Html.TextBoxFor(m => m.SomeProperty,
HtmlHelpers.ConditionalDisable(true, new { @class = "someClass"))

对我来说,这种方法的一个巨大优势是,它实际上适用于所有的 MVC HtmlHelpers,因为它们都具有接受 RouteValueDictionary 而不是匿名对象的 Overload。

警告 :
HtmlHelper.AnonymousObjectToHtmlAttributes()使用一些花哨的代码忍者工作来完成事情。我不完全确定它的性能如何,但它已经足够我用它来做什么了。你的情况可能会有所不同。

我不是特别喜欢它的名字——但是我想不出更好的名字了。重命名很容易。

我也不喜欢它的用法语法,但是我再也想不出更好的了。改变应该不难。一个对象的扩展方法是一个想法... ... 你最终会得到 new { @class = "someClass" }.ConditionalDisable(true),但是如果你只想要一个禁用属性,并且没有任何额外的东西可以添加,那么你最终会得到一个类似于 new {}.ConditionalDisable(true);的粗糙的东西,并且你最终会得到一个扩展方法,它会出现在所有的 object中... ... 这可能是不可取的。

如果您想要更简洁的语法而不需要辅助函数,那么您可以在定义用于@HTML 的 html 属性的字典时使用三元语句。复选框助手。

@Html.CheckBox("CheckBox1", true, Model.ReadOnly
? new { @class = "Class1", @disabled = Model.ReadOnly }
: null)

在本例中,Model.ReadOnly 为 false,null 作为 html 属性的字典传递。

执行添加禁用属性的客户端对我来说很有用。注意,您应该检查允许在服务器端编辑哪些字段,但是对于声明禁用属性时也是如此。

在本例中,我使用 jQuery 禁用了表单的所有子表单。

    if (Model.CanEdit)
{
<script type="text/javascript">


$(document).ready(function() {


$('#editForm *').attr('disabled', true);
});


</script>
}
@Html.TextBoxFor(m => m.FieldName, Html.FixBoolAttributes(new {
@class = "myClass",
@readonly = myFlag
}))




public static class BooleanAttributeFix
{
/// <summary>
/// Normalises HTML boolean attributes so that readonly=true becomes readonly="readonly" and
/// readonly=false removes the attribute completely.
/// </summary>
/// <param name="htmlHelper"></param>
/// <param name="htmlAttributes"></param>
/// <returns></returns>
public static RouteValueDictionary FixBoolAttributes(this HtmlHelper htmlHelper, object htmlAttributes)
{
var attrs = HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes);


foreach(var attrName in new[] { "disabled", "readonly" })
{
object value;
if(attrs.TryGetValue(attrName, out value))
{
if(isTruthy(value))
{
// Change from readonly="true" to readonly="readonly"
attrs[attrName] = attrName;
}
else
{
// Remove attribute entirely
attrs.Remove(attrName);
}
}
}
return attrs;
}


/// <summary>
/// Apply similar loose rules like javascript does for whether a value is true or not.
/// e.g. 1 = true, non-empty string = true and so on.
/// </summary>
/// <param name="val"></param>
/// <returns></returns>
private static bool isTruthy(object val)
{
if(val == null)
return false;


if(val is string)
{
return !String.IsNullOrEmpty((string)val);
}


Type t = val.GetType();


if(t.IsValueType && Nullable.GetUnderlyingType(t) == null)
{
// If a non-nullable value type such as int we want to check for the
// default value e.g. 0.
object defaultValue = Activator.CreateInstance(t);


// Use .Equals to compare the values rather than == as we want to compare
// the values rather than the boxing objects.
// See http://stackoverflow.com/questions/6205029/comparing-boxed-value-types
return !val.Equals(defaultValue);
}


return true;
}
}

你觉得我的 很简单解决方案怎么样? 它可以很容易地与两种可能的 HtmlAttributes类型一起工作:

  • Dictionary<string, object>
  • 返回文章页面

首先 将以下简单的 extension class添加到您的项目中:

public static class HtmlAttributesExtensions
{
public static IDictionary<string, object> AddHtmlAttrItem(this object obj, string name, object value, bool condition)
{
var items= !condition ? new RouteValueDictionary(obj) : new RouteValueDictionary(obj) \{\{name, value}};
return UnderlineToDashInDictionaryKeys(items);
}
public static IDictionary<string, object> AddHtmlAttrItem(this IDictionary<string, object> dictSource, string name, object value, bool condition)
{
if (!condition)
return dictSource;


dictSource.Add(name, value);
return UnderlineToDashInDictionaryKeys(dictSource);
}
private static IDictionary<string, object> UnderlineToDashInDictionaryKeys(IDictionary<string,object> items)
{
var newItems = new RouteValueDictionary();
foreach (var item in items)
{
newItems.Add(item.Key.Replace("_", "-"), item.Value);
}
return newItems;
}
}

现在看来:

示例1 < em > (HtmlAttributes类型为 Anonymous Object)

@{
var hasDisabled=true;
}


@Html.CheckBox("CheckBox1"
, true
, new { @class = "Class1"}
.AddHtmlAttrItem("disabled", "disabled", hasDisabled))
.

例2 < em > (HtmlAttributes类型为 Dictionary<string, object>)

@Html.CheckBox("CheckBox1"
, true
, new Dictionary<string, object> { { "class", "Class1" }
.AddHtmlAttrItem("disabled", "disabled", hasDisabled))
.

现在只需将 hasDisabled值改为 truefalse


Example3 < em > (多个条件属性)

@{
var hasDisabled=true;
var hasMax=false ;
var hasMin=true ;
}


@Html.CheckBox("CheckBox1"
, true
, new { @class = "Class1"}
.AddHtmlAttrItem("disabled", "disabled", hasDisabled)
.AddHtmlAttrItem("data-max", "100", hasMax)
.AddHtmlAttrItem("data-min", "50", hasMin))
.

我喜欢@gb2d 的答案,在这里它在 JS 中使用 getElementsByClassName 从这里获取 GetElementByClass () . setAttribute 不工作

<script type="text/javascript">
var list, index;
list = document.getElementsByClassName("form-control");
for (index = 0; index < list.length; ++index) {
list[index].setAttribute('disabled', true);
}
</script>