2012-10-19 4 views
7

Ich habe eine Eigenschaft, die ein IEnumerableErstellen HiddenFor IEnumerable <String> in View

public IEnumerable<string> ChangesOthersResult { get; set; } 

ich von einem Blick zurück auf die Steuerung alle Werte von ChangesOthersResult und Post sammeln müssen, ist. Wie kann ich das Ienumerable durchlaufen und versteckte Felder erstellen, die an das ViewModel im Controller binden?

foreach(var item in Model.ChangesOthersResult) 
    { 
     @Html.HiddenFor(x => x.ChangesOthersResult); 
    } 

Gibt mir die Raw SQL-Anweisung als Text.

Antwort

11

Convert ChangesOthersResult in ein Array und eine für die Ausgabe zu for-Schleife wie folgt:

for (int i = 0; i < Model.ChangesOthersResult.Length; i++)  
{ 
    @Html.Hidden("ChangesOthersResult[" + i + "]", Model.ChangesOthersResult[i]) 
} 
+0

Hinweis, Sie müssen nicht in ein Array konvertieren, das ist nur eine Möglichkeit, es zu tun. –

+0

Der Vollständigkeit halber können Sie den Code hinzufügen, der in ein Array konvertiert werden soll - danke. – niico

2

In Ihrem Modell Konstruktor, neu auf die IEnumerable ChagesOthersResult

public Model() 
{ 
    ChangesOthersResult = new List<string>(); 
} 

Dann in der Ansicht, eine for-Schleife verwenden

for(int i = 0; i < Model.ChangesOthersResult.Count; i++) 
{ 
    @Html.HiddenFor(x => x.ChangesOthersResult[i]) 
} 
+0

Ihre Erinnerung an die Initialisierung der Auflistung innerhalb des parameterlosen Konstruktors ist eine kritische Komponente, die in anderen Antworten fehlt – OneManBand

18

Ich machte dies in eine Erweiterungsmethode so für die Schleife nicht verunstalten nicht Ihre Ansicht Code:

public static class HiddenExtensions 
{ 
    public static MvcHtmlString HiddenForEnumerable<TModel, TProperty>(this HtmlHelper<TModel> helper, 
     Expression<Func<TModel, IEnumerable<TProperty>>> expression) 

    { 
     var sb = new StringBuilder(); 

     var membername = expression.GetMemberName(); 
     var model = helper.ViewData.Model; 
     var list = expression.Compile()(model); 

     for (var i = 0; i < list.Count(); i++) 
     { 
      sb.Append(helper.Hidden(string.Format("{0}[{1}]", membername, i), list.ElementAt(i))); 
     } 

     return new MvcHtmlString(sb.ToString()); 
    } 
} 

GetMemberName ist eine weitere Verlängerung Methode:

public static string GetMemberName<TModel, T>(this Expression<Func<TModel, T>> input) 
    { 
     if (input == null) 
      return null; 

     if (input.Body.NodeType != ExpressionType.MemberAccess) 
      return null; 

     var memberExp = input.Body as MemberExpression; 
     return memberExp != null ? memberExp.Member.Name : null; 
    } 

Hope this hilfreich.

+1

Dies ist der wartungsfreundlichere Weg. Werfen Sie keine Schleifen in Ihren Code, die Sie jedes Mal neu schreiben müssen, wenn Sie dies verwenden möchten. – Matthew

+0

Upvote für die Erfindung des Wortes uglify. Einfach genial. – Sentinel

+0

Wo genau würde diese Klasse gehen? – socketman

3

kann .ForEach() nicht verwenden, da @ Html.HiddenFor (x => x.ChangesOthersResult) dieselbe Element-ID erstellt, die das Modell beim Postback nicht erkennt.

for (int i = 0; i < Model.ChangesOthersResult.Count(); i++)  
{ 
    @Html.HiddenFor(x => x.ChangesOthersResult[I]); 
} 
5

Erweiterte @GitteTitter ‚s Lösung für die Listen der benutzerdefinierten Objekte:

@Html.HiddenForEnumerable(x => x.ValueTypes)  
@Html.HiddenForEnumerable(x => x.ViewModels, h=>h.Id, h=>h.Name) 
@Html.HiddenForEnumerable(x => x.ViewModels, allPublicProps: true) 

Quelle:

/// <summary> 
/// Returns hiddens for every IEnumerable item, with it's selected properties, if any memberPropsExpression provided. 
/// </summary> 
public static MvcHtmlString HiddenForEnumerable<TModel, TModelProperty>(this HtmlHelper<TModel> helper, 
    Expression<Func<TModel, IEnumerable<TModelProperty>>> expression, params Expression<Func<TModelProperty, object>>[] memberPropsExpressions) 
{ 
    var sb = new StringBuilder(); 

    var membername = expression.GetMemberName(); 
    var model = helper.ViewData.Model; 
    var list = expression.Compile()(model); 

    var memPropsInfo = memberPropsExpressions.Select(x => new 
    { 
     MemberPropName = x.GetMemberName(), 
     ListItemPropGetter = x.Compile() 
    }).ToList(); 

    for (var i = 0; i < list.Count(); i++) 
    { 
     var listItem = list.ElementAt(i); 
     if (memPropsInfo.Any()) 
     { 
      foreach (var q in memPropsInfo) 
      { 
       sb.Append(helper.Hidden(string.Format("{0}[{1}].{2}", membername, i, q.MemberPropName), q.ListItemPropGetter(listItem))); 
      } 
     } 
     else 
     { 
      sb.Append(helper.Hidden(string.Format("{0}[{1}]", membername, i), listItem)); 
     } 
    } 

    return new MvcHtmlString(sb.ToString()); 
} 

/// <summary> 
/// Returns hiddens for every IEnumerable item, with it's all public writable properties, if allPublicProps set to true. 
/// </summary> 
public static MvcHtmlString HiddenForEnumerable<TModel, TModelProperty>(this HtmlHelper<TModel> helper, 
    Expression<Func<TModel, IEnumerable<TModelProperty>>> expression, bool allPublicProps) 
{ 
    if (!allPublicProps) 
     return HiddenForEnumerable(helper, expression); 

    var sb = new StringBuilder(); 

    var membername = expression.GetMemberName(); 
    var model = helper.ViewData.Model; 
    var list = expression.Compile()(model); 

    var type = typeof(TModelProperty); 
    var memPropsInfo = type.GetProperties(BindingFlags.Public | BindingFlags.Instance) 
     .Where(x => x.GetSetMethod(false) != null && x.GetGetMethod(false) != null) 
     .Select(x => new 
     { 
      MemberPropName = x.Name, 
      ListItemPropGetter = (Func<TModelProperty, object>)(p => x.GetValue(p, null)) 
     }).ToList(); 

    if (memPropsInfo.Count == 0) 
     return HiddenForEnumerable(helper, expression); 

    for (var i = 0; i < list.Count(); i++) 
    { 
     var listItem = list.ElementAt(i); 
     foreach (var q in memPropsInfo) 
     { 
      sb.Append(helper.Hidden(string.Format("{0}[{1}].{2}", membername, i, q.MemberPropName), q.ListItemPropGetter(listItem))); 
     } 
    } 

    return new MvcHtmlString(sb.ToString()); 
} 

public static string GetMemberName<TModel, T>(this Expression<Func<TModel, T>> input) 
{ 
    if (input == null) 
     return null; 

    MemberExpression memberExp = null; 

    if (input.Body.NodeType == ExpressionType.MemberAccess) 
     memberExp = input.Body as MemberExpression; 
    else if (input.Body.NodeType == ExpressionType.Convert) 
     memberExp = ((UnaryExpression)input.Body).Operand as MemberExpression; 

    return memberExp != null ? memberExp.Member.Name : null; 
} 
+0

Ich hatte eine andere Idee für eine Erweiterung, die ich noch bauen möchte, aber ich kämpfe ein bisschen mit. Mein Ziel ist es, etwas wie @Html.HiddenForClass (m => m.SomePOCO) zu erstellen, das versteckte Felder für alle Eigenschaften einer bestimmten Klasse erzeugt. Kann ich Ihnen den Ausschnitt, an dem ich arbeite, zukommen lassen? Es ist zu groß, um es hier einzufügen ... –

+0

Besser, neue Frage dafür zu erstellen – smg

2

Wie über einen rekursiven Ansatz?

public static MvcHtmlString HiddenForEnumerable<TModel, TModelProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, IEnumerable<TModelProperty>>> expression, string prefix = null) 
{ 
    var sb = new StringBuilder(); 

    var membername = expression.GetMemberName(); 
    var model = htmlHelper.ViewData.Model; 
    var list = expression.Compile()(model); 

    var type = typeof(TModelProperty); 
    var memPropertyInfo = type.GetProperties(BindingFlags.Public | BindingFlags.Instance) 
     .Where(x => x.GetSetMethod(false) != null && x.GetGetMethod(false) != null) 
     .Select(x => new 
     { 
      Type = x.PropertyType, 
      x.Name, 
      Get = (Func<TModelProperty, object>)(p => x.GetValue(p, null)) 
     }).ToList(); 

    for (var i = 0; i < list.Count(); i++) 
    { 
     var listItem = list.ElementAt(i); 
     if (memPropertyInfo.Any()) 
     { 
      foreach (var m in memPropertyInfo) 
      { 
       var inputName = $"{prefix ?? ""}{membername}[{i}].{m.Name}"; 
       var inputValue = m.Get(listItem); 
       var genericArguments = m.Type.GetGenericArguments(); 

       if (genericArguments.Any() && IsEnumerableType(m.Type)) 
       { 
        var delegateType = typeof(Func<,>).MakeGenericType(typeof(TModel), m.Type); 
        var bodyExpression = Expression.Constant(inputValue, m.Type); 
        var paramExpression = Expression.Parameter(typeof(TModel), "model"); 
        var expressionTree = Expression.Lambda(delegateType, bodyExpression, new[] { paramExpression }); 
        var hiddenForEnumerableInfo = typeof(HtmlHelpers).GetMethod("HiddenForEnumerable"); 
        var hiddenForEnumerable = hiddenForEnumerableInfo.MakeGenericMethod(typeof(TModel), genericArguments[0]); 
        object[] args = { htmlHelper, expressionTree, inputName }; 

        sb.Append(hiddenForEnumerable.Invoke(null, args)); 
       } 
       else 
       { 
        sb.Append(htmlHelper.Hidden(inputName, inputValue)); 
       } 
      } 
     } 
     else 
     { 
      sb.Append(htmlHelper.Hidden($"{membername}[{i}]", listItem)); 
     } 
    } 

    return new MvcHtmlString(sb.ToString()); 
} 

private static string GetMemberName<TModel, T>(this Expression<Func<TModel, T>> input) 
{ 
    if (input == null) 
     return null; 

    MemberExpression memberExp = null; 

    if (input.Body.NodeType == ExpressionType.MemberAccess) 
     memberExp = input.Body as MemberExpression; 
    else if (input.Body.NodeType == ExpressionType.Convert) 
     memberExp = ((UnaryExpression)input.Body).Operand as MemberExpression; 

    return memberExp?.Member.Name; 
} 

private static bool IsEnumerableType(Type type) 
{ 
    return (type.GetInterface("IEnumerable") != null); 
} 

Beispiel:

public class Model 
{ 
    IEnumerable<Order> Orders { get; set; } 
} 

public class Order 
{ 
    public int OrderId { get; set; } 
    IEnumerable<Item> Items { get; set; } 
} 

public class Item 
{ 
    public int ItemId { get; set; } 
    public string Name { get; set; } 
} 

Usage:

@Html.HiddenForEnumerable(model => model.Orders) 

Output:

<input id="Orders_0__OrderId" name="Orders[0].OrderId" type="hidden" value="1001"> 
<input id="Orders_0__Items_0__ItemId" name="Orders[0].Items[0].ItemId" type="hidden" value="201"> 
<input id="Orders_0__Items_0__Name" name="Orders[0].Items[0].Name" type="hidden" value="Something1"> 
<input id="Orders_0__Items_1__ItemId" name="Orders[0].Items[1].ItemId" type="hidden" value="202"> 
<input id="Orders_0__Items_1__Name" name="Orders[0].Items[1].Name" type="hidden" value="Something2"> 
<input id="Orders_1__OrderId" name="Orders[1].OrderId" type="hidden" value="1002"> 
<input id="Orders_1__Items_0__ItemId" name="Orders[1].Items[0].ItemId" type="hidden" value="205"> 
<input id="Orders_1__Items_0__Name" name="Orders[1].Items[0].Name" type="hidden" value="Something5"> 
0

die gleiche für aspnetcore

using Microsoft.AspNetCore.Html; 
using Microsoft.AspNetCore.Mvc.Rendering; 
using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Linq.Expressions; 
using System.Reflection; 
using System.Text; 

namespace Proj.Helpers 
{ 
    public static class HtmlHelpers 
    { 
     public static IHtmlContent HiddenForEnumerable<TModel, TModelProperty>(this IHtmlHelper<TModel> helper, 
    Expression<Func<TModel, IEnumerable<TModelProperty>>> expression, params Expression<Func<TModelProperty, object>>[] memberPropsExpressions) 
     { 
      var hcb = new HtmlContentBuilder(); 

      var membername = expression.GetMemberName(); 
      var model = helper.ViewData.Model; 
      var list = expression.Compile()(model); 

      var memPropsInfo = memberPropsExpressions.Select(x => new 
      { 
       MemberPropName = x.GetMemberName(), 
       ListItemPropGetter = x.Compile() 
      }).ToList(); 

      for (var i = 0; i < list.Count(); i++) 
      { 
       var listItem = list.ElementAt(i); 
       if (memPropsInfo.Any()) 
       { 
        foreach (var q in memPropsInfo) 
        { 
         hcb.AppendHtml(helper.Hidden(string.Format("{0}[{1}].{2}", membername, i, q.MemberPropName), q.ListItemPropGetter(listItem))); 
        } 
       } 
       else 
       { 
        hcb.AppendHtml(helper.Hidden(string.Format("{0}[{1}]", membername, i), listItem)); 
       } 
      } 

      return hcb; 
     } 

     /// <summary> 
     /// Returns hiddens for every IEnumerable item, with it's all public writable properties, if allPublicProps set to true. 
     /// </summary> 
     public static IHtmlContent HiddenForEnumerable<TModel, TModelProperty>(this IHtmlHelper<TModel> helper, 
      Expression<Func<TModel, IEnumerable<TModelProperty>>> expression, bool allPublicProps) 
     { 
      if (!allPublicProps) 
       return HiddenForEnumerable(helper, expression); 

      var hcb = new HtmlContentBuilder(); 

      var membername = expression.GetMemberName(); 
      var model = helper.ViewData.Model; 
      var list = expression.Compile()(model); 

      var type = typeof(TModelProperty); 
      var memPropsInfo = type.GetProperties(BindingFlags.Public | BindingFlags.Instance) 
       .Where(x => x.GetSetMethod(false) != null && x.GetGetMethod(false) != null) 
       .Select(x => new 
       { 
        MemberPropName = x.Name, 
        ListItemPropGetter = (Func<TModelProperty, object>)(p => x.GetValue(p, null)) 
       }).ToList(); 

      if (memPropsInfo.Count == 0) 
       return HiddenForEnumerable(helper, expression); 

      for (var i = 0; i < list.Count(); i++) 
      { 
       var listItem = list.ElementAt(i); 
       foreach (var q in memPropsInfo) 
       { 
        hcb.AppendHtml(helper.Hidden(string.Format("{0}[{1}].{2}", membername, i, q.MemberPropName), q.ListItemPropGetter(listItem))); 
       } 
      } 

      return hcb; 
     } 

     public static string GetMemberName<TModel, T>(this Expression<Func<TModel, T>> input) 
     { 
      if (input == null) 
       return null; 

      MemberExpression memberExp = null; 

      if (input.Body.NodeType == ExpressionType.MemberAccess) 
       memberExp = input.Body as MemberExpression; 
      else if (input.Body.NodeType == ExpressionType.Convert) 
       memberExp = ((UnaryExpression)input.Body).Operand as MemberExpression; 

      return memberExp != null ? memberExp.Member.Name : null; 
     } 
    } 
} 
Verwandte Themen