2015-10-14 52 views
1

我需要将使用SignalR的Kendo Grid与具有动态列数的Datatable绑定。我怎样才能做到这一点。我可以直接将Hub中的DataTable对象传递给View吗?我的代码如下: 查看:如何使用SignalR将具有动态列数的数据表绑定到Kendo UI Grid?

@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> 

枢纽:

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; 
      } 
     } 
} 

回答

3

我想它已经比几个月更因为你问到这个问题,但这是我一直在修补的东西,并注意到还没有发布答案。这就是我所做的一切得到它的工作:

而不是使用Html.Kendo().Grid(Model)的,使用Html.Kendo().Grid<dynamic>()

传入使用ViewData列定义。我得到了DataTable的一个.Clone(),并将其分配给控制器中的ViewData["columns"],然后在绑定视图中的网格列时对其进行迭代。

Hub应该将数据作为DataTable返回。如果你决定使用服务器操作,那么你会希望你的Read方法接受一个DataSourceRequest参数并返回一个DataSourceResult对象。你需要定义你自己的DataSourceResult类,因此它的Data属性是一个DataTable。

更新:扩大你如何实现这个

所以电网是建立在多数类似的方式向任何其他,但在剑道格列生成器,你需要通过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>,按照它们在控制器中的第一列位于堆栈的第一列出现在数据表中的顺序,并将其传递给视图来解决。然后把剑道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),而不是纯文本框。

+0

谢谢!你可以用代码示例来解释这个解决方案吗? – giparekh

+0

@giparekh我更新了我的帖子,提供了更多详细信息 – Sneakster

相关问题