Telerik生态整合:Kendo UI for Angular组件在WinForms应用中的深度嵌入(二)

翻译|使用教程|编辑:龚雪|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 2025 Q2最新正式版下载

Telerik_KendoUI技术交流群(QQ):726377843

有几种情况可以应用此方法:

  • 开始从传统的WinForms应用程序迁移到Angular
  • 本地资源集成(本地数据库和其他WinForms资源)
  • 在复杂的WinForms应用程序中构建轻量级UI应用程序
  • 构建具有Web应用程序外观和感觉的WinForms应用程序
  • 执行在Docker、IIS或Cloud中运行的分布式UI
  • 无需更新WinForms应用程序客户端应用程序即可更新UI

这些来自遗留应用程序的转换场景可以帮助您在开发新的服务/应用程序时使用激活的生产资源,混合解决方案可以保留当前的WinForms,同时授权开发人员构建客户端应用程序。

在上文中(点击这里回顾>>),我们为大家介绍了Kendo UI for Angular组件在WinForms应用中的深度嵌入的一些入门指南,本文将继续介绍如何配置WinForms应用,请继续关注哟~

配置WinForms应用

在WinForms应用程序中,我将主机组件WebView2隔离在一个用户控件AngularWebControl上。因此,所有组件都具有相同的UserControl基础并共享相同的操作。

WebView2是必需的,它可以从URL中保存Angular应用程序,并与WinForms交互。

这是C#项目中的解决方案文件,看起来像这样:

Telerik生态整合:Kendo UI for Angular组件在WinForms应用中的深度嵌入

AngularDefs.cs将Angular项目的定义放在一个地方。这也可以是环境变量,以避免硬编码数据:

1. namespace app_winforsm;
2. internal static class AngularDefs
3. {
4. // URL of the Angular application
5. public const string Url = "https://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使用不同的凭据。

Telerik生态整合:Kendo UI for Angular组件在WinForms应用中的深度嵌入
本示例的工作流程

在下面的图片中,我们可以“看到”编码的流程和执行,直到回调时,最终用户点击图表,从GitHub下载源代码并尝试。

Telerik生态整合:Kendo UI for Angular组件在WinForms应用中的深度嵌入

关于慧都科技

慧都是⼀家⾏业数字化解决⽅案公司,专注于软件、⽯油与⼯业领域,以深⼊的业务理解和⾏业经验,帮助企业实现智能化转型与持续竞争优势。

慧都科技是Telerik的中国区的合作伙伴,Telerik作为用户界面领域的优秀产品,通过全栈式开发工具套件(涵盖Web、桌面、移动端及报表服务)提供160+高性能UI组件、低代码平台及实时调试工具,助力企业快速构建跨平台业务应用(如ERP、数据分析仪表盘),显著缩短开发周期(降本50%以上)并提升数据处理与界面交互效率。


标签:

本站文章除注明转载外,均为本站原创或翻译。欢迎任何形式的转载,但请务必注明出处、不得修改原文相关链接,如果存在内容上的异议请邮件反馈至chenjj@evget.com

文章转载自:慧都网

为你推荐

  • 推荐视频
  • 推荐活动
  • 推荐产品
  • 推荐文章
  • 慧都慧问
扫码咨询


添加微信 立即咨询

电话咨询

客服热线
023-68661681

TOP