编程添加属性在运行时的MVC模式 [英] Programmatically adding properties to an MVC model at runtime

查看:99
本文介绍了编程添加属性在运行时的MVC模式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想创建编程时,应用程序运行在我的模型属性。我试着遵循达林季米特洛夫回答这个帖子上的How在MVC 3基于XML文件动态创建控件

I am trying to create properties in my model programmatically when the application is run. I've tried to follow the answer by Darin Dimitrov on this post How to create controls dynamically in MVC 3 based on an XML file

我想在code转换为VB.NET。到目前为止,我有...

I am trying to convert the code to VB.NET. So far I have...

型号:

Public Class MyViewModel
    Public Property Controls As ControlViewModel()
End Class

Public MustInherit Class ControlViewModel
    Public MustOverride ReadOnly Property Type As String
    Public Property Visible As Boolean
    Public Property Label As String
    Public Property Name As String
End Class

Public Class TextBoxViewModel
    Inherits ControlViewModel
    Public Overrides ReadOnly Property Type As String
        Get
            Return "textbox"
        End Get
    End Property
    Public Property Value As String
End Class

Public Class CheckBoxViewModel
    Inherits ControlViewModel
    Public Overrides ReadOnly Property Type As String
        Get
            Return "checkbox"
        End Get
    End Property
    Public Property Value As Boolean
End Class

控制器:

Function Test() As ActionResult

    Dim model = New MyViewModel() With { _
    .Controls = New ControlViewModel() {New TextBoxViewModel() With { _
        .Visible = True, _
        .Label = "text label", _
        .Name = "TextBox1", _
        .Value = "Text appears here" _
    }, New CheckBoxViewModel() With { _
        .Visible = True, _
        .Label = "check label", _
        .Name = "CheckBox1", _
        .Value = True _
    }
    }}

    Return View("Test", model)

End Function

<httpPost()>
Function Test(model As MyViewModel) As ActionResult

    Return View("Test", model)

End Function

查看:

@ModelType MyApp.DomainModel.MyTest.MyViewModel

@Code
Using Html.BeginForm()

Dim i As Integer
For i = 0 To Model.Controls.Length - 1
End Code
    <div> 
        @Html.EditorFor(Function(model) model.Controls(i)) 
    </div> 
@Code
Next
End Code

<input type="submit" value="OK" /> 

@Code
End Using
End Code

文本框编辑模板:

TextBox Editor Template:

@modeltype MyApp.DomainModel.MyTest.TextBoxViewModel

@Html.LabelFor(Function(model) model.Value, Model.Label) 
@Html.TextBoxFor(Function(model) model.Value) 

复选框编辑模板:

Checkbox Editor Template:

@modeltype MyApp.DomainModel.MyTest.CheckBoxViewModel

@Html.LabelFor(Function(model) model.Value, Model.Label) 
@Html.CheckBoxFor(Function(model) model.Value) 

自定义模型绑定:

Custom Model Binder:

Public Class ControlModelBinder
    Inherits DefaultModelBinder

    Public Overrides Function BindModel(controllerContext As ControllerContext, bindingContext As ModelBindingContext) As Object
        Dim type = bindingContext.ValueProvider.GetValue(bindingContext.ModelName + ".Type")
        Dim name = bindingContext.ValueProvider.GetValue(bindingContext.ModelName + ".Name")
        Dim value = bindingContext.ValueProvider.GetValue(bindingContext.ModelName + ".Value")

        If type IsNot Nothing AndAlso value IsNot Nothing Then
            Select Case type.AttemptedValue
                Case "textbox"
                    Return New TextBoxViewModel() With { _
                          .Name = name.AttemptedValue, _
                          .Value = value.AttemptedValue _
                        }
                Case "checkbox"
                    Return New CheckBoxViewModel() With { _
                          .Name = name.AttemptedValue, _
                          .Value = Boolean.Parse(value.AttemptedValue.Split(","c).First()) _
                        }
            End Select
        End If

        Throw New NotImplementedException()

    End Function
End Class

Global.asax中:

Global.asax:

ModelBinders.Binders.Add(GetType(MyTest.ControlViewModel), New MyTest.ControlModelBinder())

当我运行应用程序,自定义模型绑定类型和名称的变量似乎并没有正确设置。

When I run the application, in the custom model binder the type and name variable don't seem to be set correctly.

还有什么我做错了?

推荐答案

您缺少在主视图2隐藏字段:

You are missing 2 hidden fields in your main view:

@ModelType MyApp.DomainModel.MyTest.MyViewModel

@Using Html.BeginForm()
    For i = 0 To Model.Controls.Length - 1
        @<div> 
            @Html.HiddenFor(Function(model) model.Controls(i).Type) 
            @Html.HiddenFor(Function(model) model.Controls(i).Name) 
            @Html.EditorFor(Function(model) model.Controls(i)) 
        </div> 
    Next
    @<input type="submit" value="OK" /> 
End Using

在您的code,你只有一个 EditorFor 呼吁控件属性,但你永远不指定类型通过一个隐藏字段,用于由自定义模型绑定的控件。

In your code you only have a single EditorFor call for the Controls property but you never specify the type of the control through a hidden field which is used by the custom model binder.

更新:

我也固定其中载有缺陷,因为它是更好地覆盖CreateModel方法,而不是BindModel原来的模型绑定:

I have also fixed the original model binder which contained a bug as it is better to override the CreateModel method instead of the BindModel:

Public Class ControlModelBinder
Inherits DefaultModelBinder
Protected Overrides Function CreateModel(controllerContext As ControllerContext, bindingContext As ModelBindingContext, modelType As Type) As Object
    Dim type = bindingContext.ValueProvider.GetValue(Convert.ToString(bindingContext.ModelName) & ".Type")
    If type Is Nothing Then
        Throw New Exception("The type must be specified")
    End If

    Dim model As Object = Nothing
    Select Case type.AttemptedValue
        Case "textbox"
            If True Then
                model = New TextBoxViewModel()
                Exit Select
            End If
        Case "checkbox"
            If True Then
                model = New CheckBoxViewModel()
                Exit Select
            End If
        Case "ddl"
            If True Then
                model = New DropDownListViewModel()
                Exit Select
            End If
        Case Else
            If True Then
                Throw New NotImplementedException()
            End If
    End Select

    bindingContext.ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(Function() model, model.[GetType]())
    Return model
End Function
End Class

这篇关于编程添加属性在运行时的MVC模式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆