【问题标题】:C# MVC Syntax - Recursive seeking in a template lambda (EditorFor)C# MVC 语法 - 模板 lambda 中的递归搜索 (EditorFor)
【发布时间】:2012-03-15 19:14:36
【问题描述】:

我有一个递归模型。

public class Mapping
{
    public string Value { get; set; }
    public List<Mapping> ChildMappings { get; set; }
}

我有一个 Mapping 类的 EditorTemplate。通过 EditorFor(m => m.ChildMappings) 正常渲染效果很好。

基于数组参数(2,3),我想寻找一个特定的后代节点。 (以 Mapping.ChildMappings[2].ChildMappings[3] 为例)。

我尝试在 lambda 中调用本地方法,这给了我一个关于索引器的错误以及我在模板中不能做的所有事情。

@Html.EditorFor(m => RecurseMappings(m.BodyMappings, indexes))

@functions{
    private Mapping RecurseMappings(List<Mapping> mappings, int[] indexes)
    {
        Mapping mapping = new Mapping();

        foreach (int index in indexes)
        {
            mapping = mappings[index];
            if (mapping.ChildMappings == null) { mapping.ChildMappings = new List<RequestMapping>(); }
            mappings = mappings[index].ChildMappings;
        }

        return mappings[mappings.Count - 1];
    }

目前我已经退回到至少促进硬编码数量的嵌套级别的切换,如下所示:

    string[] tokens = Model.ChildIndex.Split(',');
    int[] indexes = Array.ConvertAll<string, int>(tokens, int.Parse);

   switch (indexes.GetLength(0))
    {
        case 1:
            {
                var last = Model.BodyMappings[indexes[0]].ChildMappings.Count - 1;
@Html.EditorFor(m => m.BodyMappings[indexes[0]].ChildMappings[last])
                break;
            }

        case 2:
            {
                var last = Model.BodyMappings[indexes[0]].ChildMappings[indexes[1]].ChildMappings.Count - 1;
@Html.EditorFor(m => m.BodyMappings[indexes[0]].ChildMappings[indexes[1]].ChildMappings[last])
                break;
            }
        case 3:
            {
                var last = Model.BodyMappings[indexes[0]].ChildMappings[indexes[1]].ChildMappings[indexes[2]].ChildMappings.Count - 1;
@Html.EditorFor(m => m.BodyMappings[indexes[0]].ChildMappings[indexes[1]].ChildMappings[indexes[2]].ChildMappings[last])
                break;
            }
        case 4:
            {
                var last = Model.BodyMappings[indexes[0]].ChildMappings[indexes[1]].ChildMappings[indexes[2]].ChildMappings[indexes[3]].ChildMappings.Count - 1;
@Html.EditorFor(m => m.BodyMappings[indexes[0]].ChildMappings[indexes[1]].ChildMappings[indexes[2]].ChildMappings[indexes[3]].ChildMappings[last])
                break;
            }
        case 5:
            {
                var last = Model.BodyMappings[indexes[0]].ChildMappings[indexes[1]].ChildMappings[indexes[2]].ChildMappings[indexes[3]].ChildMappings[indexes[4]].ChildMappings.Count - 1;
@Html.EditorFor(m => m.BodyMappings[indexes[0]].ChildMappings[indexes[1]].ChildMappings[indexes[2]].ChildMappings[indexes[3]].ChildMappings[indexes[4]].ChildMappings[last])
                break;
            }
        default:
            break;
    }

那么,有没有办法将我在一个包中的工作更像是我失败的第一次尝试?我还尝试了一个 lambda 代码块,但由于无法转换为表达式树而被拒绝。

【问题讨论】:

    标签: .net asp.net-mvc lambda mvc-editor-templates


    【解决方案1】:

    好吧,这可能不是预期的方式,但是当您为要选择的对象创建新的 Html-Helper 时,它会起作用:

    @{  
        var dd =  new ViewDataDictionary<Mapping>(RecurseMappings(Model.BodyMappings, indexes));
        var dc = new MyDataContainer() { ViewData = dd };
        var help = new HtmlHelper<Mapping>(ViewContext, dc);
    }
    
    @help.EditorFor(m => m)
    

    在源文件中定义自定义数据容器,因为我找不到实现该接口的类。

    public class MyDataContainer : IViewDataContainer
    {
        public ViewDataDictionary ViewData { get; set; }
    }
    

    【讨论】:

    • 这给了我同样的运行时错误(调试表明它甚至没有尝试进入该方法)。 System.InvalidOperationException 未被用户代码处理 Message=Templates 只能用于字段访问、属性访问、单维数组索引或单参数自定义索引器表达式。
    • 这感觉更接近,因为它没有破坏,但服务于多个元素(全部在层次结构中)并且模型绑定有些不正确。结果需要按名称绑定回顶层父级,否则不能作为父模型的“BodyMappings”集合组件发布。
    猜你喜欢
    • 2022-01-11
    • 2015-09-29
    • 2011-08-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-01
    相关资源
    最近更新 更多