异步调用.NET方法并在完成时绑定到网格

Container.RetrieveItems()调用一段时间的服务,所以我想异步调用它(在检索项之后,它们被设置为Container类的List属性)。 完成检索项目后,我希望它更新一个在updatePanel内的gridView(updatePanel Mode =“Conditional”和ScriptManager EnablePartialRendering =“true”.UpdatePanel没有触发项)。

我设置了断点并逐步完成了每一步。 检索项目,网格是数据绑定然后它调用更新。 没有exception被抛出但网格没有随内容更新。 如果我使用触发器和Timer.OnTick事件将UpdatePanel设置为更新它工作正常,但是我只需要在检索项目后更新它,因此在完成服务调用后触发手动UpdatePanel.Update()将是理想的。

我做了很多搜索,但所有答案都是’你忘了调用DataBind()’

有什么我想念的吗?

private void UpdateGrid() { grid.DataSource = Container.List; grid.DataBind(); updatePanel.Update(); } protected void Page_Load(object sender, EventArgs e) { var task = Task.Factory.StartNew(Container.RetrieveItems); task.ContinueWith((x) => UpdateGrid()); } 

更新:我设置了一个更简单的测试来尝试识别问题。 我创建了一个标签,其Text属性将在方法完成时更新。 当页面加载时,它调用方法并在方法完成时调用updatePanel.Update()但没有更改。

根据Jaimes的建议,我尝试在Button_click的回发中调用手动更新,它确实更新了标签。 这就是为什么我当前的设置无法正常工作,尽管我仍然在寻找在完成异步任务时更新内容的最佳方法。

杰米走在正确的轨道上。 在呈现页面后,您的服务器无法将新数据“推送”到客户端。 客户端必须发起请求。 我会设置一个计时器或在客户端上使用JavaScript setTimeout定期轮询服务器以查看它是否完成。

Web服务方法

另一种方法是在服务器上设置Web服务,然后从您的页面调用它。 这将在新线程中执行,并在结果可用时立即异步更新网格。

首先,您需要设置WCF Web服务。 如果您不确定,有数以千计的文章。 以下是其中之一: http : //www.codeproject.com/Articles/16973/Simple-Web-Service-using-WCF-Windows-Communication

以下是我的一个项目的示例代码:

 namespace UI.Web.WebServices { [ServiceContract(Namespace = "WebServices")] [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)] public class WebServiceName { [OperationContract] [WebInvoke(ResponseFormat = WebMessageFormat.Json)] public FacilityResult[] MethodName() { FacilityService facilityService = new return facilityService .GetAssignments()).ToArray(); } } } 

从客户端调用Web服务

接下来,您需要使用JavaScript从页面中对网格进行数据绑定: http : //blog.ashmind.com/2007/06/21/client-side-databinding-with-aspnet-ajax-futures/

以下是来自同一项目的一些示例代码。 这个项目使用jQuery而不是像链接中的样本那样的纯JavaScript:

  

参考资料http://aspalliance.com/1301_Unveil_the_Data_Binding_Architecture_inside_Microsoft_ASPNET_Ajax_10__Part_1

http://aspalliance.com/1301_Unveil_the_Data_Binding_Architecture_inside_Microsoft_ASPNET_Ajax_10__Part_2

我想分享我对这个问题的完整解决方案。 虽然msigman的答案是一个很大的帮助,但它并没有让我一路走来。 我还没有找到从客户端绑定到GridView的可行解决方案,所以我正在从javascript创建网格。

1 – 设置控制器来处理请求

可以通过AJAX从客户端调用MVC控制器,允许您从客户端调用任何.NET代码。 这是一个关键部分,因为所有电源和重物都可以由控制器/服务完成,但您仍然具有javascript的灵活性。 我发布了一个完整的示例,说明如何在此处执行此操作, 从JavaScript调用ASP.NET函数? 。 (可与Webforms或MVC一起使用)。

 public class TimersController : ApiController { public HttpResponseMessage Get() { return new HttpResponseMessage( TimerRepository.Get(), // all your .NET logic can be encapsulated here new MediaTypeHeaderValue("application/json") ); } } 

2 – 使用AJAX启动请求

这可以在页面加载时通过handlding $(document).ready()事件,按钮单击或定期使用计时器来完成。

  $.ajax({ url: "api/timers", dataType: "json", success: function (result) { bindGrid(result); } }) 

3 – 将数据绑定到网格

正如我所说,我还没有找到一种方法将数据从客户端绑定到GridView。 我觉得更好的解决方案是使用完全删除GridView(这更像是一个服务器端控件而且对于这种情况不灵活),并且在它的位置你可以从Javascript生成网格。 虽然您可以手动循环数据并自己创建

,但有很多grid / ui框架可以为您完成此操作。 一个这样的UI框架有一个很好的网格对象,可以直接绑定JSON数据到Kendo UI( http://demos.kendoui.c​​om/web/grid/index.html )(以及许多其他有用的小部件)。 此SOpost包含有关javascript UI框架的更多建议https://stackoverflow.com/questions/159025/jquery-grid-recommendations 。

  function bindGrid(gridData) { var grid = $("#grid"); grid.html(""); grid.kendoGrid({ columns: [ { field: "Place", title: "Place" }, { field: "Time", title: "Time" } ], dataSource: { data: gridData }, scrollable: false }); } 
    Interesting Posts