我需要使用SignalR将Kendo Grid绑定到具有动态列数的Datatable。我怎样才能做到这一点。我可以直接将DataTable对象从Hub传递给View吗?我的代码如下: 视图:
@model System.Data.DataTable
<script>
var TestGridHub = {};
$(function () {
TestGridHub = $.connection.TestGridHub;
})
</script>
<table><tr><td>
@(Html.Kendo().Grid(Model)
.Name("TestGrid")
.Columns(columns =>
{
foreach (System.Data.DataColumn col in DataTable.Columns)
{
columns.Bound(col.ColumnName).Title("Name")
.ClientTemplate("#=name#");
}
})
.DataSource(dataSource => dataSource
.SignalR()
.PageSize(10)
.Transport(tr => tr
.Promise("hubStart")
.Hub("TestGridHub")
.Client(c => c.Read("TestGrid_Read"))
.Server(s => s.Read("TestGrid_Read"))
)
.Schema(schema => schema
.Model(m =>m.Id(p => p.Id))
))
)
</td></tr></table>
Hub:
public DataTable TestGrid_Read()
{
var queryResult = TestRepository.TestGrid_Read_Dynamic();
return queryResult;
}
存储库:
public DataTable TestGrid_Read_Dynamic()
{
using (SqlConnection connection = new SqlConnection(dbContext.Database.Connection.ConnectionString))
{
using (SqlCommand cmd = new SqlCommand("SP_TestGrid", connection))
{
var dt = new DataTable();
SqlDataAdapter adapter = new SqlDataAdapter(cmd);
adapter.SelectCommand.CommandType = System.Data.CommandType.StoredProcedure;
adapter.SelectCommand.Parameters.Add(new SqlParameter("@Id", GlobalVaribleDeclarations.Id));
adapter.Fill(dt);
return dt;
}
}
}
答案 0 :(得分:3)
我想自从你提出这个问题已经过了几个月了,但这是我一直在修补的事情,并注意到仍然没有找到答案。这就是我为使其发挥作用而做的事情:
不使用Html.Kendo().Grid(Model)
,而是使用Html.Kendo().Grid<dynamic>()
使用ViewData
传递列定义。我得到了DataTable的.Clone()
并将其分配给控制器中的ViewData["columns"]
,然后在视图中绑定Grid列时迭代它。
Hub应该将数据作为DataTable返回。如果您决定使用服务器操作,那么您希望Read方法接受DataSourceRequest参数并返回DataSourceResult对象。您需要定义自己的DataSourceResult类,以便它的Data属性是DataTable。
更新:扩展您的实施方式
因此Grid的构建方式与其他任何类似,但在Kendo Grid列构建器中,您需要遍历DataTable的列集:
.Columns(col =>
{
for(var i = 0; i < table.Columns.Count; i++)
{
if(table.Columns[i].ColumnName == "ID")
{
col.Bound(table.Columns[i].ColumnName).Hidden();
}
else
{
col.Bound(table.Columns[i].ColumnName);
}
}
}
您可以以类似的方式定义网格模型:
.Model(mod =>
{
for(var i = 0; i < table.Columns.Count; i++)
{
if(table.Columns[i].ColumnName == "ID")
{
mod.Id(table.Columns[i].ColumnName);
mod.Field(table.Columns[i].ColumnName, typeof(table.Columns[i].DataType).Editable(false);
}
else
{
mod.Field(table.Columns[i].ColumnName, typeof(table.Columns[i].DataType);
}
}
}
但是,即使定义了包含上述数据类型的模型,Kendo HTML帮助程序也不知道如何为每列选择编辑器。这可以通过构建Stack<string>
列名称来解决,它们在数据表中出现的顺序与堆栈的顶部中的第一列相同,在Controller中传递到了视野。然后使用Kendo EditorTemplates并修改它们以从堆栈中弹出一个名称并将其用于编辑器,如下所示:
//DynamicInteger.cshtml
@model int?
@{
Stack<string> columnStack = (Stack<string>)ViewData["columns"];
var name = columnStack.Pop();
}
@(Html.Kendo().IntegerTextBoxFor(m => m).Name(name)
.HtmlAttributes(new { style = "width:100%" })
.Min(int.MinValue)
.Max(int.MaxValue)
)
并更改列定义以使用修改后的EditorTemplates:
//...
}
else if (table.Columns[i].DataType == typeof(int))
{
col.Bound(table.Columns[i].ColumnName).EditorTemplateName("DynamicInteger");
}
这将导致编辑器被正确地分配给每一列,因此您可以获得格式良好的编辑器,甚至是复杂的编辑器,如DatePicker或DropDownLists,而不是纯文本框。