2012-10-19 22 views
7

Tôi có một tài sản đó là một IEnumerableTạo HiddenFor IEnumerable <String> trong Xem

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

tôi cần phải thu thập tất cả các giá trị từ ChangesOthersResult và sau từ một cái nhìn trở lại với bộ điều khiển. Làm thế nào tôi có thể lặp qua Ienumerable và tạo ra các lĩnh vực ẩn sẽ ràng buộc trở lại ViewModel trong bộ điều khiển?

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

Cung cấp cho tôi câu lệnh SQL thô dưới dạng văn bản.

Trả lời

11

Chuyển đổi ChangesOthersResult để một mảng và sử dụng một vòng lặp for để ra một cái gì đó như thế này:

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

Lưu ý, bạn KHÔNG phải chuyển đổi thành mảng, đó chỉ là một cách để thực hiện. –

+0

Để có đầy đủ, bạn có thể thêm mã để chuyển đổi thành mảng không - cảm ơn. – niico

2

Trong constructor của mô hình của bạn, mới lên IEnumerable ChagesOthersResult

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

Sau đó, trong giao diện, sử dụng một vòng lặp for

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

Lời nhắc của bạn để khởi tạo bộ sưu tập trong hàm tạo tham số là một thành phần quan trọng bị thiếu trong các câu trả lời khác – OneManBand

18

Tôi đã biến nó thành một phương pháp mở rộng để vòng lặp không làm xấu đi xem mã của bạn:

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 là một phương pháp khuyến nông:

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

Hy vọng điều này là hữu ích.

+1

Đây là cách dễ bảo trì hơn. Đừng ném vòng trong mã của bạn, bạn phải viết lại mỗi khi bạn muốn sử dụng nó. – Matthew

+0

Upvote cho phát minh của từ uglify. Thiên tài thuần túy. – Sentinel

+0

Trường hợp chính xác của lớp này sẽ đi đâu? – socketman

3

không thể sử dụng .ForEach(), vì @ Html.HiddenFor (x => x.ChangesOthersResult) sẽ tạo ID phần tử giống nhau, mà mô hình sẽ không nhận ra khi đăng lại.

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

Extended giải pháp @GitteTitter 's cho các danh sách của các đối tượng tùy chỉnh:

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

Nguồn:

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

Tôi đã có một ý tưởng cho một phần mở rộng tôi muốn xây dựng trên đầu trang này, nhưng đang đấu tranh một chút với. Mục tiêu của tôi là tạo ra một cái gì đó như @ Html.HiddenForClass (m => m.SomePOCO) tạo ra các trường ẩn cho tất cả các thuộc tính trên một lớp nhất định. Tôi có thể PM cho bạn đoạn trích tôi đang làm việc không? Nó quá lớn để dán ở đây ... –

+0

Tốt hơn để tạo câu hỏi mới cho điều này – smg

2

Làm thế nào về một cách tiếp cận đệ quy?

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

Ví dụ:

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

Cách sử dụng:

@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

tương tự cho 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; 
     } 
    } 
} 
Các vấn đề liên quan