1

我已经看到了许多与此类似的问题,但似乎没有一个答案比我已经得到的更进一步。

我有一个 ViewModel,其中包含一些复杂的类型,这些类型代表某些股票 UI 控件并附加了一些验证逻辑。我需要将这些渲染到基于 EditorTemplate/DisplayTemplate 的页面,并且还需要在提交表单时正确绑定属性,以便开发人员可以在其控制器等中使用视图模型。

一个简单的例子是

public class TestViewModel

{
    public HierarchyField MyField {get; set; }
}

最简单的是,我需要开发人员能够使用简单的方法为这个视图模型创建一个编辑器

@Html.EditorForModel()

对于 HierarchyField 的任何可编辑部分,要在该类型的自定义 EditorTemplate 中设置字段。

我已经通过使用自定义 MetaDataProvider 并覆盖 IsComplexType 来允许它渲染,虽然这不是我完全满意的东西,但确实可以完成这项工作。该解决方案的详细信息在这里(http://blogs.msdn.com/b/stuartleeks/archive/2010/04/01/collections-and-asp-net-mvc-templated-helpers-part-3.aspx?Redirected =真

我现在被困在尝试获取模型绑定以在提交表单时更新属性并调用 HierarchyField 类上的方法以执行一些自定义验证并根据该调用的结果更新 ModelState。

我首先创建了一个 DefaultModelBinder 的子类,它在 BindProperty 覆盖中具有逻辑,以检查被绑定的属性是否属于这种类型。到目前为止一切都很好。当我想调用采用预期值并尝试验证该值的实例方法时,问题就来了。BindProperty 方法给了我一个 PropertyDescriptor 的实例,它允许我找到关于我的属性的元数据,以及一个带有 ValueProvider 的 BindingContext,它允许我读取值,但是,没有我的复杂类型的实例从以下位置返回:

bindingContext.ValueProvider.GetValue(propertyDescriptor.Name + ".Value")

其中 propertyDescriptor.Name + ".Value" 等于在我的 EditorTemplate 中我有以下内容:

@Html.TextBoxFor(model => model.Value)

而不是类型,因为我显然只在回发的字段中获得了对 Value 属性的引用,所以我得到了一个 String[]。我假设,要让它工作,我需要为 HierarchyField 注册某种 ValueProvider,但理想情况下我正在寻找更通用的东西,因为我有许多这些类型要设置,所有其中子类是一个通用抽象类型(它们都有一个名为“Value”的属性,它返回其值的字符串表示形式)。

老实说,这整个过程似乎很痛苦,以至于我觉得我错过了一些非常简单的事情。不幸的是,我确实需要它是通用的,因为有几十个这样的字段,而且我确实需要这个模型,或者类似的东西来处理它们的字段验证,因为 DataAnnotation 验证属性无法做到这一点。我无法创建与特定视图模型相关的自定义代码,我更愿意最小化与特定字段相关的代码,更喜欢适用于基类 (FieldBase) 及其任何子类的代码。

如果有人需要看到它,很高兴发布额外的代码。

4

1 回答 1

6

我一直在几个项目中使用复杂类型和自定义渲染,没有任何问题。也许我误解了你的问题,但我想我可以发布一个简化的工作示例(MVC4),也许它会帮助你。

在我的示例中,复杂类型定义为:

[ComplexType]
public class AccessType
{
  public bool ReadAccess { get; set; }
  public bool EditAccess { get; set; }
}

模型定义为:

public class UserAccess 
{
  [Key]
  public Int32 UserId { get; set; }
  public AccessType AccessType { get; set; }
}

我在Views\Shared\DisplayTemplates中创建了以下名为AccessType.cshtml的显示模板,用于处理复杂类型在显示时的呈现。

@model [path to complex type].AccessType
@Html.LabelFor(m => m.EditAccess,"Read access")
@Html.DisplayFor(m => m.ReadAccess) 
@Html.LabelFor(m => m.EditAccess, "Edit access")
@Html.DisplayFor(m => m.EditAccess)

我在Views\Shared\EditorTemplates中创建了以下名为AccessType.cshtml的编辑模板,用于处理复杂类型在编辑时的呈现。

@model [path to complex type].AccessType
@Html.LabelFor(m => m.ReadAccess,"Read access")
@Html.CheckBoxFor(m => m.ReadAccess) 
@Html.LabelFor(m => m.EditAccess, "Edit access")
@Html.CheckBoxFor(m => m.EditAccess) 

对于使用这种复杂类型的模型的视图文件,我进行了以下更改:

_CreateOrEdit.cshtml文件中,我添加了这一行来呈现复杂类型部分:

@Html.EditorFor(m => m.AccessType)

...到Delete.cshtmlDetails.cshtml我添加了:

@Html.DisplayFor(m => m.AccessType)

...并在Index.cshtml中添加了:

@Html.DisplayFor(_ => item.AccessType)

这就是我渲染和使用复杂类型所需的全部内容。

如果您的问题更复杂,请添加更多代码来说明。

于 2013-06-05T15:31:25.257 回答