1
@{IEnumerable<BC.Models.APPLICATION> data = ViewBag.list;} 
@Html.Grid(data).Columns(columns =>
{
columns.Add(c => c.APPLICATION_NO).Titled("Application No").Filterable(true);
})

但我想做这样的事情:

@if(some conditon)
{
@{IEnumerable<BC.Models.APPLICATION> data = ViewBag.list;} 
}
else
{
@{IEnumerable<BC.Models.RIGHTS> data = ViewBag.list;} 
}
@Html.Grid(data).Columns(columns =>
{
columns.Add(c => c.APPLICATION_NO).Titled("Application No");
})

但是它不起作用,任何人都可以对此有所了解。
现在,如果我做这样的事情,它会起作用

@if(some conditon)
    {
    @{IEnumerable<BC.Models.APPLICATION> data = ViewBag.list;} 
    @Html.Grid(data).Columns(columns =>
    {
    columns.Add(c => c.APPLICATION_NO).Titled("Application No");
    })
    }
    else
    {
    @{IEnumerable<BC.Models.RIGHTS> data = ViewBag.list;} 
    @Html.Grid(data).Columns(columns =>
    {
    columns.Add(c => c.APPLICATION_NO).Titled("Application No");
    })
    }

我的问题是两个模型类中都存在 APPLICATION_NO 属性,所以我不想使用

    @Html.Grid(data).Columns(columns =>
    {
    columns.Add(c => c.APPLICATION_NO).Titled("Application No");
    })

在我的代码中两次。

4

3 回答 3

5

您的问题是您没有使用 MVC 中最重要的概念之一:视图模型。

至于您的最后一条评论,您要使用的是视图模型,即专门创建的用于将数据发送到视图以显示它的类。

为此:

  1. 创建一个具有APPLICATION_NO(视图模型类所需)的公共类
  2. 创建另一个公共类,这将是您的视图模型。这是一个在剃刀模板上根据需要对数据进行整形的类(在这种情况下,它将保存 1 中定义的类的列表)
  3. 在您的控制器中,返回将模型作为第二个参数传递的视图。即不使用ViewBag/ ViewData,而是使用视图模型,就像这样return View("ViewName", model)
  4. 在您的视图中使用模型:使用提供的变量声明模型类型@model并在 Razor 模板中使用它Model

通过这种方式,您可以在服务器上调整数据,并避免在 Razor 模板中包含大量代码(不建议这样做)。而且,当然,你有智能感知,你的模板变成了类型。

代码 1:

public class ApplicationModel
{
   public int APPLICATION_NO {get; set;}
}

代码 2:

public class ApplicationsViewModel
{
   public List<ApplicationModel> Applications { get; set; }
}

3 的代码(在控制器内部)

var model = new ApplicationsViewModel();

if (...) // include the condition to choose the kind of data inside the list
{
   model.Applications = list.Select(item =>
     new ApplicationModel { APPLICATION_NO = item.APPLICATION_NO } ).ToList()
}
else
{
   // same code here, for the other kind of data in the list
}

// return the view with this model
return View("ApplicationView", model);

4的代码:

// decalre the model type at the beginning
@model YourNamespace.ApplicationViewModel;

// access the model using the Model variable
@Html.Grid(Model.Applications).Columns(columns =>
  {
  columns.Add(c => c.APPLICATION_NO).Titled("Application No");
  })

这允许您构建具有多个优点的 MVC 应用程序,例如可测试性、代码重用、可读性或ModelState. 相信我,许多这些事情真的非常重要,特别是ModelState.

除了可以在视图模型中使用代码注释(为 HTML 助手提供额外信息的属性)之外,这些属性还可以提供标签、验证和其他一些自动功能。

不要怀疑在视图模型中包含所有需要的属性。

使用视图模型允许您创建一个临时类,而无需更改您的域或业务层类,即您不需要使用接口、代码注释等。然而很多时候在业务类中添加代码注释并将它们嵌套在视图模型中是很有趣的。

请记住,有时您可以使用相同的视图模型将数据发送回服务器,并将其指定为 POST 操作的参数类型。

顺便说一句,接口解决方案是一个很好的解决方案,但是这个解决方案不需要接口。(此解决方案使用该接口会有更好的实现,但这是您的选择)。

于 2014-06-30T11:02:09.130 回答
3
@if(some conditon)
{
@{IEnumerable<BC.Models.APPLICATION> data = ViewBag.list;} 
}
else
{
@{IEnumerable<BC.Models.RIGHTS> data = ViewBag.list;} 
}
@Html.Grid(data).Columns(columns =>
{
columns.Add(c => c.APPLICATION_NO).Titled("Application No");
})

代码无法工作,因为数据被声明到 if 块中。如果网格只能在两个类的共享字段上工作,您可以考虑使用 APPLICATION 和 RIGHTS 将实现的接口并更改如下代码:

@{IEnumerable<BC.Models.IAPPLICATION_NO> data = (IEnumerable<BC.Models.IAPPLICATION_NO>)ViewBag.list;} 
@Html.Grid(data).Columns(columns =>
{
columns.Add(c => c.APPLICATION_NO).Titled("Application No");
})

其中 IAPPLICATION_NO 是一个接口,如:

public interface IAPPLICATION_NO
{
    string APPLICATION_NO { get; }
}

我不知道APPLICATION_NO是什么,所以我使用了string,接口只能定义get for grid。

否则,如果您需要为这两种类型显示不同的数据,您应该考虑在 if 块中使用两个视图或不同的网格声明。

我在 VS 上研究了我的答案样本:

我附上代码:

public interface AInterface
{
    string AProperty { get; }
}

public class AList : AInterface
{
    public string AProperty { get; set; }
}

public class BList : AInterface
{
    public string AProperty { get; set; }
}

这些是课程

现在控制器:

public class TestController : Controller
{
    public ActionResult Index()
    {
        var random = new Random((int)DateTime.Now.Ticks);

        if (random.Next() % 2 == 0)
            ViewBag.List = new List<AList> { new AList { AProperty = "Atestvalue" } };
        else
            ViewBag.List = new List<BList> { new BList { AProperty = "Atestvalue" } };

        return View();
    }
}

和观点:

@{
    ViewBag.Title = "Index";
    IEnumerable<TestMvcApplication.Interfaces.AInterface> test = ViewBag.List;
}

<h2>Index</h2>

@foreach (var item in test)
{
    <div>
        @item.AProperty
    </div>
}

如您所见,这解决了您的问题

不使用接口:

@{IEnumerable<dynamic> data = (IEnumerable<dynamic>)ViewBag.list;} 
@Html.Grid(data).Columns(columns =>
{
columns.Add(c => c.APPLICATION_NO).Titled("Application No");
})

但是您丢失了 IntelliSense 完成,如果该成员丢失,我认为您会收到运行时错误。

我尝试了您的 Grid 程序集,但它使用 c# Expression 并且与动态不兼容。另一种解决方案可能是在控制器中使用 LINQ 将一个列表转换为另一个:

IEnumerable<BC.Models.Application> data;
if (some condition)
{
    data = applicationList; //applicationList's type is IEnumerable<BC.Models.Application>
}
else
{
    data = rightsList.Select(t => new Application { APPLICATION_NO = t.APPLICATION_NO }); //rightsList's type is IEnumerable<BC.Models.RIGHTS>
}

ViewBag.list = data;

在视图中,您可以将发布的工作代码保留在问题的顶部。您没有多类型 IEnumerable 支持,因为您只使用一种类型,但没有在这些类之间使用公共接口我认为我们必须进行反射,但我认为很难编写该代码。

于 2014-06-27T09:46:07.377 回答
0

为什么不

@{string columnName = "default column name";
if(some_condition)
{
    // I'm not sure what's going on with the data variable
    columnName = "alternate column name";
}
else
{
    // Again, do your stuff with the data variable
}
}
@Html.Grid(data).Columns(columns =>
{
    columns.Add(c => c.APPLICATION_NO).Titled(columnName);
})

我认为如果你试图在你的观点上过于聪明,你最终会得到(充其量)令人困惑的代码。用于渲染的网格IEnumerable<A>不适用于渲染IEnumerable<B>,除非A:ISomeInterfaceB:ISomeInterface并且网格渲染ISomeInterface。或者,只需将列名作为视图模型的属性传递。

于 2014-06-27T13:43:22.757 回答