【问题标题】:Using Editable attribute on MVC 3 view model在 MVC 3 视图模型上使用 Editable 属性
【发布时间】:2012-04-25 23:07:54
【问题描述】:

我希望使用属性将视图模型属性标记为只读,以便视图字段在渲染视图中是只读的。应用 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())

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

【问题讨论】:

  • 在创建视图中,我们希望用户能够为所有字段提供初始值,但一旦进入编辑视图,其中一些字段需要变为只读。

标签: asp.net-mvc-3 attributes


【解决方案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)
}

【讨论】:

  • 这种方法的问题是 ReadOnly 在 mvc 中有一个明确的目的 - 它防止绑定到特定字段。它不是 UI 相关字段,而是模型绑定相关字段。通过在其中存储其他信息,您可以实现一个单独的目的。只是我的 .02 :)
【解决方案2】:

EditableAttribute documentation 声明:

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

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

不幸的是,这意味着使用此属性对 MVC 中的验证没有任何影响。这感觉是错误的,但如果您考虑在 MVC 框架中实现它需要什么,它是有道理的。例如,在典型的“编辑”视图中,用户执行初始 GET 请求,其中填充模型(通常来自数据库记录)并提供给视图以呈现给用户。然后用户进行一些编辑,然后提交表单。提交表单会导致从 POST 参数构造模型的 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

【讨论】:

  • 这个类既不强制也不保证字段是可编辑的。当我发布问题时,这让我感到困惑。你说得对,使用可编辑和只读属性只是指示性的,你必须寻找然后相应地呈现你的视图。我最近在这个问题上花了一些时间,并认为我现在已经解决了。请参阅下面的答案。
  • @StevenChalk - 很高兴看到您找到了解决方案!我在我的项目中加入了与您类似的解决方案。
【解决方案3】:

不知道你是否已经弄清楚了,但我们使用

System.ComponentModel.ReadOnlyAttribute

用法

[ReadOnly(true)]

【讨论】:

  • 这似乎不起作用,我总是在视图中看到false
【解决方案4】:

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

[隐藏输入(DisplayValue=true)]

该字段已显示但不可编辑。

【讨论】:

  • 值得一提的是HiddenInputAttributeSystem.Mvc命名空间中。 Here is the doc. 如果您要注释业务模型类而不是使用 ViewModel,那么使您的业务模型依赖于 MVC 框架是没有意义的。另一方面,如果您使用带有注释的 ViewModel,则此属性无需任何额外代码即可工作。
【解决方案5】:

你有不同的创建场景吗?您允许初始值的任何特殊原因?我问是因为documentation 说:

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

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

【讨论】:

  • 文档所说的是 AllowInitialValue 将设置为与 AllowEdit 相同的值,除非您在属性声明中明确设置 AllowInitialValue。
  • 是的,我收集到了,想说的是,如果您将其保留为假,它应该可以工作。设置为 false 时是否有效?我现在看到您有两种情况,但只是好奇其中至少一种是否有效。
  • 我最初使用了可编辑属性,但没有应用 AllowInitialValue 并且 AllowInitialValue 明确设置为 false。似乎没有任何组合有效。
猜你喜欢
  • 2012-10-26
  • 1970-01-01
  • 2016-05-08
  • 1970-01-01
  • 2011-07-15
  • 1970-01-01
  • 2012-06-09
  • 1970-01-01
  • 2012-01-24
相关资源
最近更新 更多