【问题标题】:MVC Html.DisplayFor for Lists of Derived ModelsMVC Html.DisplayFor 用于派生模型列表
【发布时间】:2014-05-18 02:49:40
【问题描述】:

假设我有三个类:Derived1ViewModelDerived2ViewModelBaseViewModel,它们是 Derived1ViewModelDerived2ViewModel 的超类。

我有一个 DisplayTemplate,其模型为 List<BaseViewModel>,我想从用作模型的视图中调用此模板 List<Derived1ViewModel>List< Derived2ViewModel>

如果我尝试这样做,则会触发一个异常,指出它无法将 List<Derived1ViewModel>List<Derived2VIewModel> 转换为 List<BaseViewModel>. 如果我尝试应用诸如 @Html.DisplayFor(model=>model.Cast<BaseViewModel>.ToList(), "MyTemplate") 之类的强制转换,则会引发 InvalidOperationException。

详情: [InvalidOperationException:模板只能与字段访问、属性访问、单维数组索引或单参数自定义索引器表达式一起使用。]

这个问题可以解决还是需要采取其他方法?

【问题讨论】:

    标签: c# asp.net-mvc razor frontend


    【解决方案1】:

    请注意,@Html.DisplayFor(model=>model, "MyTemplate") 中的第一个参数不是 Model。这是一个Expression,将在 Model 上进行评估。

    模型隐式传递给 MVC 表达式编译器(我认为使用 ViewData),模型的类型仍然是您在 Razor 页面开头声明的类型。它与表达无关。表达式只是表示需要什么数据,以 model 作为起始参数。

    话虽如此,试一试:

    @Html.DisplayFor(model=>model.Select(dm=>(BaseViewModel)dm).ToList(), "MyTemplate")
    

    虽然我有一种感觉,您可能会遇到 MVC 表达式评估障碍,它只能处理一组特定的表达式。 (常量表达式、成员访问等)

    我们可以根据您的结果得出结论。

    【讨论】:

    • 它仍然会触发 InvalidOperationException。 [InvalidOperationException:模板只能与字段访问、属性访问、单维数组索引或单参数自定义索引器表达式一起使用。]
    【解决方案2】:

    如果您的模型是 IEnumerble

    的子类

    MVC 会将其渲染为 SomeModel,

    首先,您不能将 List 直接转换为 List

    因此,要么在视图中转换为 List 并使用 Display( 而不是 DisplayFor,要么将显示模板的模型类型从 List 更改为 IEnumerable

    其次,您必须在 UIHintAttribute 中设置模板名称或将其作为参数传递给 DisplayFor

    【讨论】:

    • 您能否详细说明并举个例子?为什么使用 Html.Display 而不是 Html.DisplayFor?
    • 抱歉用我的手机打字 我记得 Html.Display(m => m.MyProperty.Cast().ToList(), "MyTemplate") 不是有效的语法。所以你必须使用 var newModel = Model.MyProperty.Cast().ToList(); Html.Display(newModel, "MyTemplate") 之类的
    • 或将 DisplayTemplate 的模型从 List 更改为 IEnumerable @model IEnumerable @{ var model = Model.ToList(); }
    • 通过将模型模板从 IEnumerable 更改为 BaseViewModel 解决了问题。
    【解决方案3】:

    通过使用BaseViewModel 的模板而不是List<BaseViewModel> 解决了这个问题。这样,我可以将任何派生类型传递给模板(例如:Derived1ViewModel、Derived2ViewModel)。

    例子:

    @*Derived1 View*@
    @model List<Derived1ViewModel>
    @for(var i = 0; i < Model.Count; i++)
    {
        int i1 = i;
        @Html.DisplayFor(model=>model[i1], "MyTemplate")
    }
    
    @*Derived2 View*@
    @model List<Derived2ViewModel>
    @for(var i = 0; i < Model.Count; i++)
    {
        int i1 = i;
        @Html.DisplayFor(model=>model[i1], "MyTemplate")
    }
    
    @*Template*@
    @model BaseViewModel
    <p>It works @Model.Name</p>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-08-26
      • 1970-01-01
      • 2012-05-29
      相关资源
      最近更新 更多