翻译|使用教程|编辑:龚雪|2025-06-18 11:26:54.460|阅读 6 次
概述:本文将为大家介绍如何在Telerik UI for WinForms应用中使用Kendo UI for Angular组件来交换通信和事件,欢迎下载新版组件体验!
# 界面/图表报表/文档/IDE等千款热门软控件火热销售中 >>
Telerik DevCraft包含一个完整的产品栈来构建您下一个Web、移动和桌面应用程序。它使用HTML和每个.NET平台的UI库,加快开发速度。Telerik DevCraft提供完整的工具箱,用于构建现代和面向未来的业务应用程序,目前提供UI for ASP.NET MVC、Kendo UI、UI for ASP.NET AJAX、UI for WPF、UI for Xamarin、Reporting等众多控件。
在这篇文章中,我们将演示如何在Telerik UI for WinForms应用程序中使用Kendo UI for Angular组件。您将了解其中的陷阱,以及如何从WinForms实现与Angular的通信,并从Angular获取事件。
Telerik_KendoUI技术交流群(QQ):726377843
有几种情况可以应用此方法:
这些来自遗留应用程序的转换场景可以帮助您在开发新的服务/应用程序时使用激活的生产资源,混合解决方案可以保留当前的WinForms,同时授权开发人员构建客户端应用程序。
在上文中(),我们为大家介绍了Kendo UI for Angular组件在WinForms应用中的深度嵌入的一些入门指南,本文将继续介绍如何配置WinForms应用,请继续关注哟~
在WinForms应用程序中,我将主机组件WebView2隔离在一个用户控件AngularWebControl上。因此,所有组件都具有相同的UserControl基础并共享相同的操作。
WebView2是必需的,它可以从URL中保存Angular应用程序,并与WinForms交互。
这是C#项目中的解决方案文件,看起来像这样:
AngularDefs.cs将Angular项目的定义放在一个地方。这也可以是环境变量,以避免硬编码数据:
1. namespace app_winforsm; 2. internal static class AngularDefs 3. { 4. // URL of the Angular application 5. public const string Url = "//aw.jsmotta.com/"; 6. 7. // Route to the graph component 8. public const string RouteGraph = "graph-control"; 9. 10. // Verb to receive data in the Angular component 11. public const string ChartVerb = "receiveData"; 12. }
AngularWebControl.cs保存着接口的任务,我们在下面的代码中添加了一些解释。它定义组件的接口,读取click事件,并将其传递给事件处理程序。
1. using Microsoft.Web.WebView2.Core; 2. using Microsoft.Web.WebView2.WinForms; 3. using System.Text.Json; 4. using Telerik.WinControls.UI; 5. 6. namespace app_winforsm; 7. internal partial class AngularWebControl : UserControl 8. { 9. // WebView Control 10. private WebView2? _webView; 11. 12. // Event to handle chart item click - it could be only OnItemClick 13. public event EventHandler? OnChartItemClick; 14. 15. // The data to be passed to the Angular component 16. private dynamic? Data { get; set; } 17. 18. // a label to show the title of the control 19. // in a real-world scenario, we can extend this component and add other controls 20. private RadLabel? Title { get; set; } 21. 22. public AngularWebControl() 23. { 24. InitializeComponent(); 25. } 26. public async void LoadData(string title, dynamic data) 27. { 28. if (Title == null) 29. { 30. Title = new RadLabel 31. { 32. Text = title, 33. Dock = DockStyle.Top, 34. Width = this.Width, 35. AutoSize = true, 36. Font = new Font("Arial", 12, FontStyle.Bold), 37. ThemeName = "Windows11" 38. }; 39. 40. 41. this.Controls.Add(Title); 42. 43. Title.MouseUp += Title_MouseUp; 44. } 45. 46. this.Title.Text = title; 47. 48. if (_webView == null) 49. { 50. _webView = new WebView2 51. { 52. Visible = true, 53. Dock = DockStyle.Fill 54. }; 55. 56. this.Controls.Add(_webView); 57. 58. var userDataFolder1 = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), $"AngularWinFormsApp_{this.Name}"); 59. 60. var environment1 = await CoreWebView2Environment.CreateAsync(userDataFolder: userDataFolder1); 61. 62. // The environment is created to avoid loss of data in the session 63. await _webView.EnsureCoreWebView2Async(environment1); 64. 65. 66. _webView.CoreWebView2.NavigationCompleted += WebView_NavigationCompleted; 67. 68. // Event to receive data from Angular 69. _webView.CoreWebView2.WebMessageReceived += CoreWebView2_WebMessageReceived; 70. 71. _webView.CoreWebView2.Navigate($"{AngularDefs.Url}{AngularDefs.RouteGraph}"); 72. 73. if (OnChartItemClick != null) 74. { 75. // This is the trick to receive data from the Angular component 76. await _webView.CoreWebView2.ExecuteScriptAsync(@" 77. window.addEventListener('MyClick', function(event) { 78. window.chrome.webview.postMessage(event.detail.message); 79. }); 80. "); 81. } 82. } 83. 84. // Send the data to the Angular component 85. this.Data = data; 86. } 87. 88. private void Title_MouseUp(object? sender, MouseEventArgs e) 89. { 90. if (e.Button == MouseButtons.Right) 91. { 92. // An easter egg to show the WebView console 93. // when pressing right click on the RadLabel 94. ShowWebViewConsole(); 95. } 96. } 97. 98. // Event handler to handle messages received from the WebView2 99. private void CoreWebView2_WebMessageReceived(object? sender, CoreWebView2WebMessageReceivedEventArgs e) 100. { 101. // Retrieve the message from the event 102. var message = e.TryGetWebMessageAsString(); 103. 104. // Display the message or perform any action 105. OnChartItemClick?.Invoke(message, EventArgs.Empty); 106. } 107. private async void WebView_NavigationCompleted(object? sender, CoreWebView2NavigationCompletedEventArgs e) 108. { 109. if (_webView == null) return; 110. 111. _webView.Visible = true; 112. 113. if (!e.IsSuccess) 114. { 115. // Return a custom messsage based on the error to avoid default Webview error page 116. switch (e.WebErrorStatus) 117. { 118. 119. case CoreWebView2WebErrorStatus.ConnectionAborted: 120. ShowErrorMessage("Connection refused. Please make sure the server is running and try again."); 121. break; 122. case CoreWebView2WebErrorStatus.Unknown: 123. case CoreWebView2WebErrorStatus.CertificateCommonNameIsIncorrect: 124. case CoreWebView2WebErrorStatus.CertificateExpired: 125. case CoreWebView2WebErrorStatus.ClientCertificateContainsErrors: 126. case CoreWebView2WebErrorStatus.CertificateRevoked: 127. case CoreWebView2WebErrorStatus.CertificateIsInvalid: 128. case CoreWebView2WebErrorStatus.ServerUnreachable: 129. case CoreWebView2WebErrorStatus.Timeout: 130. case CoreWebView2WebErrorStatus.ErrorHttpInvalidServerResponse: 131. case CoreWebView2WebErrorStatus.ConnectionReset: 132. case CoreWebView2WebErrorStatus.Disconnected: 133. case CoreWebView2WebErrorStatus.CannotConnect: 134. case CoreWebView2WebErrorStatus.HostNameNotResolved: 135. case CoreWebView2WebErrorStatus.OperationCanceled: 136. case CoreWebView2WebErrorStatus.RedirectFailed: 137. case CoreWebView2WebErrorStatus.UnexpectedError: 138. case CoreWebView2WebErrorStatus.ValidAuthenticationCredentialsRequired: 139. case CoreWebView2WebErrorStatus.ValidProxyAuthenticationRequired: 140. default: 141. ShowErrorMessage("An error occurred while loading the page."); 142. break; 143. } 144. return; 145. } 146. 147. var jsonData = JsonSerializer.Serialize(Data); 148. 149. // Here is the connection with the interface (verb) defined in the Angular component 150. var script = $"window.{AngularDefs.ChartVerb}({jsonData});"; 151. 152. await _webView.CoreWebView2.ExecuteScriptAsync(script); 153. } 154. 155. }
Message.cs是Angular应用中click事件交互的模型。
下面是FormMain.cs中控件的用例,我们动态地添加了一个控件,并使用工具箱中的拖放功能添加了另一个控件。需要注意的是,需要一个不同的属性名来避免WebView2会话上的冲突,这是一个陷阱。
在这个示例中使用模拟数据,但您可能会在实际应用程序中从数据源读取数据。
1. using System.Text.Json; 2. using Telerik.WinControls; 3. using Telerik.WinControls.UI; 4. 5. namespace app_winforsm; 6. 7. public partial class FormMain : RadForm 8. { 9. private readonly AngularWebControl? _angularWebControl; 10. 11. public FormMain() 12. { 13. InitializeComponent(); 14. 15. // Load the AngularWebControl programatically 16. 17. _angularWebControl = new AngularWebControl { Name = "_angularWebControl" }; 18. _angularWebControl.Dock = DockStyle.Fill; 19. 20. splitPanel1.Controls.Add(_angularWebControl); 21. 22. // Subscribe to the OnChartItemClick event 23. _angularWebControl.OnChartItemClick += AngularWebControl_OnChartItemClick; 24. 25. LoadData(); 26. } 27. 28. private void AngularWebControl_OnChartItemClick(object? sender, EventArgs e) 29. { 30. if (sender is null) 31. return; 32. 33. var message = 34. JsonSerializer.Deserialize<Message>(sender.ToString() ?? throw new Exception("Data is not a json.")); 35. 36. RadMessageBox.ThemeName = "Windows11"; 37. RadMessageBox.Show($"You clicked on {message.Category} with value {message.Value}", "Chart Item Clicked", 38. MessageBoxButtons.OK, RadMessageIcon.Info); 39. } 40. 41. private void LoadData() 42. {
注意:在生产项目中,您将从存储库加载数据!
43. 44. var data = new[] 45. { 46. new { name = "Gastroenteritis", value = 40, color = "red" }, 47. new { name = "Appendicitis", value = 25, color = "blue" }, 48. new { name = "Cholecystitis", value = 15, color = "green" }, 49. new { name = "Pancreatitis", value = 10, color = "yellow" }, 50. new { name = "Diverticulitis", value = 10, color = "orange" } 51. }; 52. 53. _angularWebControl?.LoadData("Common gastro deseases in hospitals", data); 54. 55. var dataAges = new[] 56. { 57. new { name = "0-10", value = 1, color = "red" }, 58. new { name = "11-20", value = 10, color = "blue" }, 59. new { name = "21-30", value = 20, color = "green" }, 60. new { name = "31-40", value = 25, color = "yellow" }, 61. new { name = "41-50", value = 15, color = "orange" }, 62. new { name = "51-60", value = 20, color = "purple" }, 63. new { name = "61-70", value = 8, color = "brown" }, 64. new { name = "71+", value = 7, color = "pink" } 65. }; 66. 67. this.angularWebControl1.LoadData("Patiant ages in gastro deseases", dataAges); 68. } 69. }
这两个图表共享相同的界面和UserControl,它们处于不同的web会话中。会话被隔离是为了保存数据,并且出于安全考虑,同一个UserControl可以根据作为参数传递的URL使用不同的凭据。
在下面的图片中,我们可以“看到”编码的流程和执行,直到回调时,最终用户点击图表,从GitHub并尝试。
慧都是⼀家⾏业数字化解决⽅案公司,专注于软件、⽯油与⼯业领域,以深⼊的业务理解和⾏业经验,帮助企业实现智能化转型与持续竞争优势。
慧都科技是Telerik的中国区的合作伙伴,Telerik作为用户界面领域的优秀产品,通过全栈式开发工具套件(涵盖Web、桌面、移动端及报表服务)提供160+高性能UI组件、低代码平台及实时调试工具,助力企业快速构建跨平台业务应用(如ERP、数据分析仪表盘),显著缩短开发周期(降本50%以上)并提升数据处理与界面交互效率。
本站文章除注明转载外,均为本站原创或翻译。欢迎任何形式的转载,但请务必注明出处、不得修改原文相关链接,如果存在内容上的异议请邮件反馈至chenjj@dpuzeg.cn
文章转载自:慧都网