2012-03-06 2 views
1

Я пытаюсь создать свойства в своей модели программно, когда приложение запущено. Я постарался ответить Дарин Димитров на этот пост How to create controls dynamically in MVC 3 based on an XML fileПрограммно добавление свойств модели MVC во время выполнения

Я пытаюсь преобразовать код в VB.NET. До сих пор у меня есть ...

Модель:

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 редактор шаблона:

@modeltype MyApp.DomainModel.MyTest.TextBoxViewModel 

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

Галочка Редактор шаблона:

@modeltype MyApp.DomainModel.MyTest.CheckBoxViewModel 

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

Пользовательские модели 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:

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

При запуске приложения в пользовательской модели связующего типа и имени переменная, похоже, не установлена ​​правильно.

Что я могу делать неправильно?

ответ

2

Вы не хватает 2 скрытых полей в главном окне:

@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 

В коде у вас есть только один EditorFor вызов для Controls собственности, но вы никогда не указать тип управления через скрытое поле, которое используется связующим устройством специальной модели.


UPDATE:

Я также установил оригинальную модель связующее вещество, которое содержало ошибку, как это лучше переопределить метод CreateModel вместо 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 
+0

совершенны, спасибо. –

+0

У меня возникла проблема с созданием моей модели, когда она исходит из базы данных. Пример кода, создающего несколько элементов управления, отлично работает, но я не уверен, как это сделать из базы данных. Я попытался объявить переменную как новый ControlViewModel, но это не работает из-за абстрактного класса. Любая идея, как я могу сопоставить данные, относящиеся к модели? –

+0

@cw_dev, я не могу ответить на этот вопрос, так как вы не указали никаких подробностей о вашей точной схеме базы данных и о том, какую технологию доступа к базе данных вы используете. Вероятно, стоит начать новый вопрос, поскольку это больше не связано с ASP.NET MVC, а больше с доступом к базе данных в .NET. –

Смежные вопросы