在View中创建HiddenFor IEnumerable <String>

use*_*794 10 c# linq asp.net-mvc entity asp.net-mvc-3

我有一个IEnumerable属性

public IEnumerable<string> ChangesOthersResult { get; set; }
Run Code Online (Sandbox Code Playgroud)

我需要从ChangesOthersResult收集所有值并从视图发回到控制器.我如何遍历Ienumerable并创建将绑定回控制器中的ViewModel的隐藏字段?

foreach(var item in Model.ChangesOthersResult)
   {
       @Html.HiddenFor(x => x.ChangesOthersResult);
   }
Run Code Online (Sandbox Code Playgroud)

给我Raw SQL语句作为文本.

Git*_*ter 20

我把它变成了一个扩展方法,所以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());
    }
}
Run Code Online (Sandbox Code Playgroud)

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;
    }
Run Code Online (Sandbox Code Playgroud)

希望这是有帮助的.


小智 14

将ChangesOthersResult转换为数组并使用for循环输出如下内容:

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


smg*_*smg 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)
Run Code Online (Sandbox Code Playgroud)

资源:

/// <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;
}
Run Code Online (Sandbox Code Playgroud)