2012-10-19 21 views
7

में HiddenFor IEnumerable बनाना मैं एक संपत्ति है कि एक IEnumerable देखें

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

मैं एक दृश्य वापस नियंत्रक से ChangesOthersResult और पद से सभी मूल्यों को इकट्ठा करने की जरूरत है। मैं Ienumerable के माध्यम से कैसे लूप कर सकता हूं और छिपे हुए फ़ील्ड बना सकता हूं जो नियंत्रक में ViewModel पर वापस बंधेगा?

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

मुझे कच्चे SQL कथन को टेक्स्ट के रूप में दे रहा है।

उत्तर

11

Convert ChangesOthersResult एक सरणी के लिए इस्तेमाल करते हैं और उत्पादन कुछ करने के लिए पाश के लिए एक का उपयोग इस तरह:

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

नोट, आपको किसी सरणी में कनवर्ट करने की आवश्यकता नहीं है, यह करने का एक ही तरीका है। –

+0

पूर्णता के लिए आप एक सरणी में बदलने के लिए कोड जोड़ सकते हैं - धन्यवाद। – niico

2

अपने मॉडल के निर्माता में, नए IEnumerable ChagesOthersResult

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

तब ध्यान में रखते हुए, एक पाश के लिए

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

पैरामीटर रहित कन्स्ट्रक्टर के भीतर संग्रह को आरंभ करने के लिए आपका अनुस्मारक अन्य उत्तरों से अनुपलब्ध एक महत्वपूर्ण घटक है – OneManBand

18

मैंने इसे एक विस्तार विधि में बनाया ताकि पाश आपके विचार कोड तोड़कर बिगाड़ना नहीं करता है:

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; 
    } 

आशा इस उपयोगी है:

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 एक और विस्तार विधि है।

+1

यह अधिक रखरखाव तरीका है। अपने कोड में लूप फेंक न दें, आपको हर बार फिर से लिखना होगा जब आप इसका उपयोग करना चाहते हैं। – Matthew

+0

शब्द uglify के आविष्कार के लिए उपरोक्त। प्रतिभाशाली। – Sentinel

+0

यह कक्षा कहां जाएगी? – socketman

3

.EEach() का उपयोग नहीं कर सकता है, क्योंकि @ Html.HiddenFor (x => x.ChangesOthersResult) एक ही तत्व आईडी बना देगा, जिसे मॉडल पोस्टबैक पर पहचाना नहीं जाएगा।

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

विस्तारित @GitteTitter के कस्टम वस्तुओं की सूची के लिए समाधान:

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

स्रोत:

/// <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

मेरे पास एक विस्तार के लिए एक और विचार था जिसे मैं इस पर बनाना चाहता हूं, लेकिन थोड़ा सा संघर्ष कर रहा हूं। मेरा लक्ष्य @ Html.HiddenForClass (m => m.SomePOCO) जैसे कुछ बनाना है जो किसी दिए गए वर्ग पर सभी गुणों के लिए छिपे हुए फ़ील्ड बनाता है। क्या मैं पीएम आपको स्निपेट कर सकता हूं जिस पर मैं काम कर रहा हूं? पेस्ट करने के लिए यह बहुत बड़ा है ... –

+0

इसके लिए नया प्रश्न बनाने के लिए बेहतर – smg

2

कैसे एक पुनरावर्ती दृष्टिकोण के बारे में?

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); 
} 

उदाहरण:

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; } 
} 

उपयोग:

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

आउटपुट:

<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

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; 
     } 
    } 
} 
संबंधित मुद्दे