ASP.NET MVC 动态 HTML 属性

8

我的视图上有几个元素,如文本框、下拉框等。它们都有一些唯一的属性,如下所示:

<%: Html.DropDownListFor(model => model.MyModel.MyType, EnumHelper.GetSelectList< MyType >(),new { @class = "someclass", @someattrt = "someattrt"})%>

我想通过设置另一个属性“disabled”来创建我的页面的只读版本。

有人知道如何使用可以全局设置的变量来实现吗?

类似于:

If(pageReadOnly){
isReadOnlyAttr  = @disabled = "disabled";
}else 
{
isReadOnlyAttr   =”” 
} 

<%: Html.DropDownListFor(model => model.MyModel.MyType, EnumHelper.GetSelectList< MyType >(),new { @class = "someclass", @someattrt = "someattrt",isReadOnlyAttr})%>

我不想使用JavaScript来完成这个任务。

2个回答

7

我认为你需要的是我做过类似的事情 - 基本上,我的系统有几个不同的用户,其中一组在网站上只具有只读权限。为了实现这一点,我在每个视图模型上都有一个变量:

public bool Readonly { get; set; }

这是关于IT技术的翻译内容。根据用户角色权限,我在我的模型/业务逻辑层中设置了一个属性。

然后,我创建了一个扩展方法来扩展DropDownListFor Html Helper,该方法接受一个布尔值,指示下拉列表是否应为只读:

using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Web.Mvc;
using System.Web.Mvc.Html;

public static class DropDownListForHelper
{
    public static MvcHtmlString DropDownListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, IEnumerable<SelectListItem> dropdownItems, bool disabled)
    {
        object htmlAttributes = null;

        if(disabled)
        {
            htmlAttributes = new {@disabled = "true"};
        }

        return htmlHelper.DropDownListFor<TModel, TProperty>(expression, dropdownItems, htmlAttributes);
    }
}

请注意,您还可以创建其他需要更多参数的实例。
在我的看法中,我只是导入了我的Html助手扩展的命名空间,然后将只读的视图模型变量传递给DropDownListFor Html助手。
<%@ Import Namespace="MvcApplication1.Helpers.HtmlHelpers" %>

<%= Html.DropDownListFor(model => model.MyDropDown, Model.MyDropDownSelectList, Model.Readonly)%>

我对TextBoxFor、TextAreaFor和CheckBoxFor都进行了相同的操作,它们似乎都工作得很好。希望这能帮到你。


谢谢回复,是的,这就是我想要的。 - Bart

6

与其禁用下拉列表,为什么不将其替换为所选选项...如果您需要对大量内容进行此操作,则应考虑拥有只读视图和可编辑视图...

<% if (Model.IsReadOnly) { %>
    <%= Model.MyModel.MyType %>
<% } else { %>
    <%= Html.DropDownListFor(model => model.MyModel.MyType, EnumHelper.GetSelectList< MyType >(),new { @class = "someclass", someattrt = "someattrt"})%>
<% } %>

顺带一提,只有当属性名是保留字,例如"class"时,才需要使用"@"转义属性名。

更新

好的,我可以给你一个答案,但前提是你在实现之前先阅读这些内容。

MVC的核心思想是分离关注点。将本应是视图关注的逻辑放入控制器中是对MVC的滥用。请不要这样做。任何与视图相关的东西,例如HTML、属性、布局等,在"控制器区"都不应该出现。因为你想改变视图而导致控制器必须改变是不正确的。

重要的是,你理解MVC试图实现什么,并且下面的例子违反了整个模式,将视图的东西完全放错了位置。

正确的解决方法是创建一个"读取"视图和一个"编辑"视图,或者将任何条件逻辑放在视图中。但以下是一种做你想做的事情的方法。:(

将此属性添加到模型中。

public IDictionary<string, object> Attributes { get; set; }

在控制器中,您可以有条件地设置属性:

model.Attributes = new Dictionary<string, object>();
model.Attributes.Add(@"class", "test");
if (isDisabled) {
    model.Attributes.Add("disabled", "true");
}

在你的视图中使用属性:

<%= Html.TextBoxFor(model => model.SomeValue, Model.Attributes)%>

这个视图上有很多东西,我们仅需要它来展示一些可以实现的“演示功能”。 我想避免创建一个单独的视图或在每个元素上添加“if”语句。我更愿意从表单中删除提交按钮并添加禁用属性。可行吗? - Bart
我已添加了一个示例来实现此操作。仅仅因为它是可能的,并不意味着您必须这样做......请阅读示例上面的内容。 - Fenton
谢谢您的更新,那是我的最初方法,但不同的元素具有不同的属性,所以我不能将相同的model.Attributes传递给它们所有的元素。 - Bart
你可以拥有不同的属性集合,或者你可以将视图上的字典与模型上的禁用属性字典合并。 - Fenton

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