C# MVC Html.DisplayFor用于派生模型列表

C# MVC Html.DisplayFor用于派生模型列表,c#,asp.net-mvc,razor,frontend,C#,Asp.net Mvc,Razor,Frontend,假设我有三个类:Derived1ViewModel、Derived2ViewModel和BaseViewModel,它们是Derived1ViewModel和Derived2ViewModel的超类 我有一个DisplayTemplate,它有一个列表作为模型,我想从使用列表或列表作为模型的视图中调用此模板 如果我尝试这样做,会触发一个异常,说明它无法将列表或列表转换为列表。如果我尝试应用@Html.DisplayFormodel=>model.cast.ToList之类的强制转换,MyTemp

假设我有三个类:Derived1ViewModel、Derived2ViewModel和BaseViewModel,它们是Derived1ViewModel和Derived2ViewModel的超类

我有一个DisplayTemplate,它有一个列表作为模型,我想从使用列表或列表作为模型的视图中调用此模板

如果我尝试这样做,会触发一个异常,说明它无法将列表或列表转换为列表。如果我尝试应用@Html.DisplayFormodel=>model.cast.ToList之类的强制转换,MyTemplate将引发InvalidOperationException

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

这个问题可以解决吗?或者有必要采取另一种方法吗?

请注意,在@Html.DisplayFormodel=>model中,MyTemplate的第一个参数不是模型。它是将在模型上计算的表达式

该模型使用ViewData隐式地传递给MVC表达式编译器,我认为该模型的类型仍然是您在Razor页面开始时声明的类型。这与表达无关。该表达式仅指示以模型作为起始参数所需的数据

话虽如此,不妨试一试:

@Html.DisplayFor(model=>model.Select(dm=>(BaseViewModel)dm).ToList(), "MyTemplate")
尽管我有一种感觉,您可能会遇到MVC表达式求值的障碍,它只能处理一组特定的表达式。常量表达式、成员访问等


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

如果您的模型是IEnumerble的子类

MVC将把它呈现为SomeModel

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

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


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

通过使用BaseViewModel模板而不是列表解决了此问题。通过这种方式,我可以将任何派生类型传递给模板ex: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>

它仍然会触发InvalidOperationException。[InvalidOperationException:模板只能与字段访问、属性访问、一维数组索引或单参数自定义索引器表达式一起使用。]能否详细说明并给出一个示例?为什么要使用Html.Display而不是Html.DisplayFor?很抱歉,因为我记得Html.Displaym=>m.MyProperty.CastBaseViewModel.ToList,我的模板不是有效的语法。因此,您必须使用var newModel=Model.MyProperty.CastBaseViewModel.ToList;Html.DisplaynewModel,MyTemplate类似于此,或者将DisplayTemplate的模型从List更改为IEnumerable@model IEnumerable@{var model=model.ToList;}通过将模型模板从IEnumerable更改为BaseViewModel,解决了此问题。