在MVC 3视图模型上使用Editable属性

时间:2012-04-13 15:02:01

标签: asp.net-mvc-3 attributes

我希望使用属性将视图模型属性标记为只读,以便视图字段仅在渲染视图中读取。应用System.ComponentModel.DataAnnotations.EditableAttribute似乎是我需要的确切属性,但它似乎不起作用,即文本框字段仍然可编辑。我环顾四周,找不到答案,只找到一些相关的问题。下面应用的可编辑属性在渲染视图时不起作用。

[Display(Name = "Last Name")]
[Editable(false, AllowInitialValue = true)]
public string LastName { get; set; }

我可以使用像这样的视图助手函数来实现只读行为,但我的偏好是在模型属性上使用属性。

@functions {
    object getHtmlAttributes()
    {
    if (@ViewBag.Mode == "Edit")
    {
      return new {style = "width:100px;background:#ff6;", @readonly = "readonly"};
    }

    return new { style = "width:100px;" };  
}
} 

@Html.TextBoxFor(model => model.FirstName, getHtmlAttributes())

其他属性完全正常,包括自定义验证属性。你能告诉我数据注释可编辑属性是否在这个上下文中起作用,应该像上面那样工作还是需要做其他事情?感谢。

5 个答案:

答案 0 :(得分:4)

EditableAttribute documentation州:

  

数据字段上存在EditableAttribute属性表示用户是否应该能够更改字段的值。

     

此类既不强制也不保证字段可编辑。基础数据存储可能允许更改字段,无论是否存在此属性。

不幸的是,这意味着使用此属性对MVC中的验证没有任何影响。这感觉不对,但是如果你想一想在MVC框架中实现它需要什么,这是有道理的。例如,在典型的“编辑”视图中,用户执行初始GET请求,其中填充模型(通常来自DB记录)并将其提供给要呈现给用户的视图。然后用户进行一些编辑,然后提交表单。提交表单会导致从POST参数构造Model的 new 实例。验证器很难确保该字段在两个对象实例中具有相同的值,因为其中一个实例(来自GET请求的第一个实例)已经被处理掉了。

如果属性没有功能,为什么还要费心去使用呢?

我最好的猜测是,他们希望开发人员在代码中使用它来显示意图。更实际的是,您还可以编写自己的自定义代码来检查是否存在此属性...

AttributeCollection attributes = TypeDescriptor.GetAttributes(MyProperty);
if (attributes[typeof(EditableAttribute)].AllowEdit)
{
   // editable
}
else
{
   // read-only
}

另请注意,这些DataAnnotation属性不仅适用于MVC应用程序,还可用于许多不同类型的应用程序。即使MVC对此属性没有做任何特殊处理,other frameworks have implemented functionality/validation for this attribute

答案 1 :(得分:2)

我自己刚刚解决了这个问题。

[HiddenInput(DisplayValue = true)]

显示该字段但不可编辑。

答案 2 :(得分:1)

您有不同的创建方案吗?您允许初始值的任何特殊原因?我问,因为documentation说:

  

因为您通常希望两个属性包含相同的值,   AllowInitialValue属性设置为的AllowEdit值   类构造函数。

我在想如果你将它设置为false并且没有明确声明AllowInitialValue它会起作用。

答案 3 :(得分:1)

发现在模型上使用Editable而不是Readonly完全相同。

[ReadOnly(true)] //or
[Editable(false)]
public string Name { get; set; }

在查询视图本身的属性属性时,此语法确实有效。当属性为Editable(true)

时也可以使用
@if (ViewData.ModelMetadata.Properties.Where(p => p.PropertyName == "Name").First().IsReadOnly)
{ 
    @Html.TextBoxFor(model => model.Name, new { style = "width:190px; background-color: #ffffd6", @readonly =  "readonly" })
} 
else
{
    @Html.TextBoxFor(model => model.Name, new { style = "width:190px; " })
}

在这里使用编辑器模板一个简单的字符串模板:

@model String
@{
IDictionary<string, object> htmlAttributes = new Dictionary<string, object>();
if (ViewData.ModelMetadata.IsReadOnly) //this will be looking at the actual property not the complete model
{
htmlAttributes.Add("style", "width:100px; background-color:#ffffd6");
htmlAttributes.Add("readonly", "readonly");
@Html.TextBox("", Model, htmlAttributes)
}

答案 4 :(得分:0)

不知道你是否已经解决了这个问题,但我们使用了

System.ComponentModel.ReadOnlyAttribute

用法

[ReadOnly(true)]