C#.Net Webアプリがあります。そのアプリでは、システムにログインしているユーザーに基づいて、条件付きで_Html.TextBoxFor
_コントロール(_Html.DropDownListFor
_コントロール)を無効にする必要があります。使ってみた
_ @Html.TextBoxFor(model => model.ProposalName, new { @ViewBag.IsDisabled })
_
コントローラで_@ViewBag.IsDisabled
_がString.Emptyまたは"disabled"に設定されています。ただし、これは_IsDisabled='disabled'
_または_IsDisabled=""
_としてレンダリングされるため、コントロールは無効になりません。試したとき
_@Html.TextBoxFor(model => model.ProposalName, new { @ViewBag.Disabled })
_
_ViewBag.Disabled
_にテキストが含まれていなくても、コントロールは常に無効でした。 Html.TextBoxFor()
コントロールを条件付きで無効にするにはどうすればよいですか?
試して
@Html.TextBoxFor(model => model.ProposalName, ViewBag.Disabled ? (object)new { disabled="disabled" } : new {})
@epignosisxが投稿したソリューションは機能しますが、他の属性を追加する場合は、両方のオブジェクト(disabled
を持つものと空になったもの)を追加する必要があるため、問題になる可能性があります。
さらに悪いことに、他のboolプロパティがある場合は、それぞれの組み合わせごとに4つの異なるオブジェクトがあるためです。
ここでの最善の解決策は(少しコードを追加して)、HtmlHelperの拡張メソッドを構築して、ブールプロパティをパラメーターとして受け取ることです。
public static MvcHtmlString TextBoxDisabledFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, bool disabled, object htmlAttributes = null)
{
return TextBoxDisabledFor(htmlHelper, expression, disabled, HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
}
public static MvcHtmlString TextBoxDisabledFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, bool disabled, IDictionary<string, object> htmlAttributes)
{
if (htmlAttributes == null)
htmlAttributes = new Dictionary<string, object>();
if (disabled)
htmlAttributes["disabled"] = "disabled";
return htmlHelper.TextBoxFor(expression, htmlAttributes);
}
これと同じ問題が発生したため、独自のHtmlHelper
拡張メソッドを作成することにしました。
_public static MvcHtmlString Disable(this MvcHtmlString helper, bool disabled)
{
if (helper == null)
throw new ArgumentNullException();
if (disabled)
{
string html = helper.ToString();
int startIndex = html.IndexOf('>');
html = html.Insert(startIndex, " disabled=\"disabled\"");
return MvcHtmlString.Create(html);
}
return helper;
}
_
これは、コントロールを無効にするかどうかを示すブール値を受け入れます。最初の_disabled="disabled"
_のすぐ内側に_>
_を追加するだけです。
以下のように使用できます。
@Html.TextBoxFor(model => model.ProposalName).Disable(true)
これが拡張機能を必要とせず、1つのHTML属性のみに制限しない方法を使用しています。モデルには「Disabled」という名前のブールプロパティがあると想定していますが、三項演算子のブールと評価される限り、そこに必要なものを置くことができます。
@Html.TextBoxFor(model => model.Whatever,
new Dictionary<string, object>() {
{ "size", "5" },
{ "class", "someclasshere" },
{ model.Disabled ? "disabled" : "data-notdisabled", "disabled" }
})
標準のショートカット表記の制限は、属性の名前を動的にできないことです。正しいタイプのディクショナリを作成することにより、属性名を動的にすることができ、そのディクショナリを属性のディクショナリとしてテキストボックスに渡します。フィールドを無効にしない場合、「disabled」という名前の属性の代わりに「data-notdisabled」という名前の属性を渡します。この属性はブラウザで無視されます。
@Jamesの答えを拡張して、disabled
属性が既に存在する場合は更新/削除し、存在しない場合は追加するこのHtmlHelper拡張機能を作成しました。
_public static MvcHtmlString Disable(this MvcHtmlString helper, bool disabled) {
string html = helper.ToString();
var regex = new Regex("(disabled(?:=\".*\")?)");
if (regex.IsMatch(html)) {
html = regex.Replace(html, disabled ? "disabled=\"disabled\"" : "", 1);
} else {
regex = new Regex(@"(\/?>)");
html = regex.Replace(html, disabled ? "disabled=\"disabled\"$1" : "$1", 1);
}
return MvcHtmlString.Create(html);
}
_
また、自己終了タグ(_<input />
_など)ともうまく機能します。
使用法は同じです:
_@Html.TextBoxFor(model => model.PropertyName).Disable(true)
_
@Html.DropDownListFor()
と@Html.TextBoxFor()
の両方でテスト済み。