可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I have a painfully simple view model
public class TellAFriendViewModel
{
public string Email1 { get; set; }
public string Email2 { get; set; }
public string Email3 { get; set; }
public string Email4 { get; set; }
public string Email5 { get; set; }
}
And then the corresponding inputs on my view, but I'm wondering if there is a better way (such as a loop) to write similar TextBoxes to my view:
@using (Html.BeginForm()){
@Html.AntiForgeryToken()
@Html.TextBoxFor(vm => vm.Email1)
@Html.TextBoxFor(vm => vm.Email2)
@Html.TextBoxFor(vm => vm.Email3)
@Html.TextBoxFor(vm => vm.Email4)
@Html.TextBoxFor(vm => vm.Email5)
}
回答1:
You should access
ViewData.ModelMetadata.Properties
. No reason to double the reflection effort, plus it figures out DataAttributes metadata for you.
@foreach(var property in ViewData.ModelMetadata.Properties)
{
<div class="editor-line">
<label>@(property.DisplayName??property.PropertyName)</label>
@Html.Editor(property.PropertyName)
</div>
}
回答2:
You should consider using an array.
However, if you wanted to go with reflection, it would look like this:
@foreach (var prop in Model.GetType().GetProperties())
{
@(Html.TextBox(prop.Name, prop.GetValue(Model, null)))
}
回答3:
Unless i'm missing something, I don't know why no-one has suggested this. Why is everyone looping and/or using reflection??
public class TellAFriendViewModel
{
public ICollection<EmailViewModel> Emails { get; set; } // populate 5 of them in ctor or controller
}
public class EmailViewModel
{
public string Email { get; set; }
}
View:
@using (Html.BeginForm()){
@Html.AntiForgeryToken()
@Html.EditorFor(model => model.Emails)
}
EditorTemplates\EmailViewModel.cshtml
@Html.TextBoxFor(model => model.Email)
Loops are NEVER required in MVC. I repeat. NEVER
回答4:
This is the accepted way to do it
foreach (var prop in ViewData.ModelMetadata.Properties.Where(pm => !pm.HideSurroundingHtml && pm.ShowForEdit && !ViewData.TemplateInfo.Visited(pm))) {
<div class="form-group">
<label>
@prop.GetDisplayName()
@if (prop.IsRequired)
{
<span class="required">*</span>
}
</label>
@Html.Editor(prop.PropertyName)
@Html.ValidationMessage(prop.PropertyName, new {@class = "help-block"})
</div>
}
回答5:
You can use Reflection to loop through each property of your model...as below
Type type = Model.GetType(); // Model is the object you are binding with in your view
PropertyInfo[] properties = type.GetProperties();
foreach (var property in properties)
{
// Code to create your text box for the property
}
Hope this helps...
回答6:
you could use reflection over the properties, or a simple for loop to generate the same HTML as is generated in your solution, but what's your goal?
For simplicity, what you have wins.
Reflection
foreach (var prop in typeof(whatever).GetProperties(BindingFlags.Instance | BindingFlags.Public))
{
@Html.TextBox(prop.Name, prop.GetValue(Model));
}
Loop
var numberProperties = 5; // you could also do typeof(whatever).GetProperties(BindingFlags.Instance | BindingFlags.Public).Count();
@for(var i = 0; i < numberProperties; i++){
<input type="text" name="Email@i" id="Email@i"/>
}
回答7:
Perhaps like this?
public class TellAFriendViewModel
{
List<string> Emails { get; set; }
public TellAFriendViewModel()
{
Emails = new List<string>(5);
}
}
@using (Html.BeginForm()){
@Html.AntiForgeryToken()
@for(int count = 0 ; count < model.Emails.Count; count++)
{
@Html.TextBoxFor(vm => vm.Emails[count])
}
}