14

IEnumerableであるプロパティがあります

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

ChangesOthersResultからすべての値を収集し、ビューからコントローラーに投稿する必要があります。Ienumerableをループして、コントローラーのViewModelにバインドする非表示フィールドを作成するにはどうすればよいですか?

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

生のSQLステートメントをテキストとして提供しています。

4

7 に答える 7

22

これを拡張メソッドにしたので、forループがビューコードを醜くしません。

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は、別の拡張メソッドです。

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

これがお役に立てば幸いです。

于 2013-10-22T10:06:24.887 に答える
17

ChangesOthersResultを配列に変換し、forループを使用して次のようなものを出力します。

for (int i = 0; i < Model.ChangesOthersResult.Length; i++ )    
{
   @Html.Hidden("ChangesOthersResult[" + i + "]", Model.ChangesOthersResult[i])
}
于 2012-10-19T20:49:03.803 に答える
8

カスタムオブジェクトのリストに対する拡張@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;
}
于 2016-02-05T16:23:14.947 に答える
4

再帰的なアプローチはどうですか?

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">
于 2016-11-11T05:30:47.837 に答える
3

@ Html.HiddenFor(x => x.ChangesOthersResult)は同じ要素IDを作成するため、.ForEach()は使用できません。これは、モデルがポストバックで認識されません。

for (int i = 0; i < Model.ChangesOthersResult.Count(); i++ )    
{
    @Html.HiddenFor(x => x.ChangesOthersResult[I]);
}
于 2015-11-12T16:48:13.997 に答える
2

モデルのコンストラクターで、IEnumerableChagesOthersResultを新しくします

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

次に、ビューでforループを使用します

for(int i = 0; i < Model.ChangesOthersResult.Count; i++)
{
  @Html.HiddenFor(x => x.ChangesOthersResult[i])
}
于 2012-10-19T20:48:47.610 に答える
1

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;
        }
    }
}
于 2018-02-21T10:42:26.150 に答える