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最新正式版下载

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

  • 开始从传统的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%以上)并提升数据处理与界面交互效率。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/pingmian/85936.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/85936.shtml
英文地址,请注明出处:http://en.pswp.cn/pingmian/85936.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

红帽全球副总裁曹衡康:开源AI开启企业级应用新纪元

在生成式AI技术迅猛发展的今天&#xff0c;ChatGPT、DeepSeek、元宝等AI应用已不再仅仅是科技前沿的象征&#xff0c;而是切实地融入到了我们的工作与生活之中&#xff0c;为企业带来了前所未有的变革机遇。对于企业而言&#xff0c;如何有效利用AI技术降本增效&#xff0c;已成…

异构计算解决方案(兼容不同硬件架构)

异构计算解决方案通过整合不同类型处理器&#xff08;如CPU、GPU、NPU、FPGA等&#xff09;&#xff0c;实现硬件资源的高效协同与兼容&#xff0c;满足多样化计算需求。其核心技术与实践方案如下&#xff1a; 一、硬件架构设计 异构处理器组合‌ 主从协作模式‌&#xff1a…

中科米堆汽车车门自动化三维检测3D尺寸测量设备自动外观检测

汽车的每一个零部件的质量都关乎着整车的性能与安全。汽车车门作为车辆的重要组成部分&#xff0c;不仅承担着保护车内人员安全的关键职责&#xff0c;其外观质量与尺寸精度也直接影响着消费者的第一印象和驾驶体验。 汽车车门制造涉及众多复杂的工艺流程&#xff0c;从冲压成…

Python 数据分析与可视化 Day 4 - Pandas 数据筛选与排序操作

&#x1f3af; 今日目标 掌握 Pandas 中 groupby() 的使用方式学会使用 agg() 方法进行多个聚合掌握 pivot_table() 构建透视表结合分组与排序进行更深入的分析 &#x1f9ee; 一、基本分组统计&#xff08;groupby&#xff09; ✅ 分组 单列聚合 df.groupby("性别&qu…

智能营销系统对企业的应用价值

在当前快速迭代的商业环境中&#xff0c;企业与客户的连接方式正经历前所未有的深刻变革。传统的市场策略在数据洪流和日益个性化的消费者需求面前&#xff0c;效能正逐步递减。 企业决策者普遍面临一个核心挑战&#xff1a;如何在复杂多变的市场中&#xff0c;实现营销资源的最…

docker镜像中集成act工具

# 使用官方 Ubuntu 22.04 基础镜像 FROM ubuntu:22.04# 安装系统依赖并清理缓存 RUN apt-get update && \apt-get install -y --no-install-recommends \curl \git \make \gcc \g \libssl-dev \pkg-config \&& \apt-get clean && \rm -rf /var/lib/apt…

Docker 与 Containerd 交互机制简单剖析

#作者&#xff1a;邓伟 文章目录 一、背景&#xff1a;Docker 架构的演进之路1.1 从自研运行时到 OCI 标准化1.2 现行架构分层模型 二、核心交互组件解析2.1 通信协议&#xff1a;gRPC 双向流的应用2.2 镜像生命周期管理交互2.2.1 镜像拉取流程&#xff08;以 docker pull 为例…

C++ Vector 基础入门操作

一、Vector初始化&#xff1a;5种常用方式 ​​1. 默认构造​​ 创建空容器&#xff0c;适用于后续动态添加元素&#xff1a; std::vector<int> vec; // 空vector&#xff0c;size0 2. 指定大小和初值​​ 预分配空间并初始化元素&#xff1a; std::vector<int>…

社会治理创新平台PPT(48页)

社会治理创新背景 社会治理创新旨在加强和完善基层社会管理和服务体系&#xff0c;提升政府效能&#xff0c;强化城乡社区自治和服务功能。自党的十六届四中全会提出“推进社会管理体制创新”以来&#xff0c;社会治理创新已成为政府工作的重要篇章。 社会治理创新现状与挑战…

论文笔记:Answering POI-Recommendation Questions using TourismReviews

2021 CIKM 1 intro 根据贝恩公司&#xff08;Bain & Company&#xff09;2019年的一份报告&#xff0c;旅行者在预订前通常会进行33至500次网页搜索 部分用户会访问超过50个旅游网站&#xff0c;三分之一的上网时间都用于与旅行相关的活动。在某些情况下&#xf…

带约束的高斯牛顿法求解多音信号分离问题

一、信号模型与优化问题建立 1. 复信号模型 设观测的复信号由两个单频复指数信号加噪声组成&#xff1a; x [ n ] A 0 e j ( 2 π f 0 n T s ϕ 0 ) A 1 e j ( 2 π f 1 n T s ϕ 1 ) w [ n ] , n 0 , 1 , … , N − 1 x[n] A_0 e^{j(2\pi f_0 n T_s \phi_0)} A_1 e…

Java并发编程中高效缓存设计的哲学

文章目录 引言详解缓存的设计和演进基于缓存存储运算结果锁分段散列减小锁粒度异步化提升处理效率原子化避免重复运算小结参考引言 本文将基于并发编程和算法中经典的哈希取模、锁分段、 异步化、原子化。这几个核心设计理念编写逐步推演出一个相对高效的缓存工具,希望对你有…

MATLAB的.mat文件

.mat文件是MATLAB的专有二进制数据文件格式&#xff0c;用于保存MATLAB工作空间中的变量和数据。 主要特点&#xff1a; 1. 存储内容&#xff1a; 各种类型的变量&#xff08;数组、矩阵、结构体、单元数组等&#xff09;函数句柄、对象稀疏矩阵多维数组 2. 文件特性&#…

ICM-20948 Wake on Motion功能开发全过程(7)

接前一篇文章:ICM-20948 Wake on Motion功能开发全过程(6) 探索工作 深入探索 上一回讲到,笔者在InvenSense官网上找到了实现Wake on Motion功能的指导文档。其中主要步骤如下: 本回就来结合文档中的步骤,详细讲解每一步。 (1)第1步 —— 初始化所有配置 注意,文档…

Dipal D1:数字人时代的全新人机关系形态

在科技不断突破的今天,虚拟与现实之间的界限正变得越来越模糊。Dipal D1 作为全球首款搭载2.5K曲面OLED显示屏的3D AI数字人硬件产品,不仅是一款情感陪伴设备,更是AI、AIGC、动漫文化与情感科技深度融合下的全新交互入口。它代表着“孤独经济”、“创作者经济”和“虚拟互动…

Linux离线编译安装nginx

Linux离线安装nginx 1.切换到root用户 #切换到root用户 su - #退出root用户 exit2.目录操作 #切到根目录 cd / #查看目录 ls #切目录 cd /home/... #到对应的目录下解压3.安装Nginx 在有网络的设备上下载以下文件&#xff1a; Nginx&#xff1a;从 nginx.org/en/download…

Qt PyQt与PySide技术-C++库的Python绑定

Qt PyQt与PySide技术-C库的Python绑定 一、概述二、区别于联系1、PyQt&#xff1a;Riverbank Computing的解决方案a、发展历程b、许可模式c、技术特点 2、PySide&#xff1a;Qt官方的Python绑定a、发展历程b、许可模式c、技术特点 三、对比许可证功能与兼容性社区与维护其他差异…

使用.detach()代替requires=False避免计算图错误

解决对一个对象多次BP更新时造成的RuntimeError: you can only change requires_grad flags of leaf variables.问题_解决对一个对象多次bp更新时造成的问题-CSDN博客 代码中存在一个特征需要参与辅助损失的计算&#xff0c;由于需要反复进行反向传播更新&#xff0c;计算图容易…

linux+docker+ollama+git常用指令

1、Linux命令 新建txt文件&#xff1a;touch xxx.txt 给txt文件夹权限&#xff1a;chmod x xxx.txt 查看日志&#xff1a;tail -f xxx.log / less xxx.log 根据关键字查看日志&#xff1a;grep "error" 文件名 查看端口状态&#xff1a;netstat -an|grep xxxxx 查看…

【八股消消乐】消息队列优化—系统架构设计

&#x1f60a;你好&#xff0c;我是小航&#xff0c;一个正在变秃、变强的文艺倾年。 &#x1f514;本专栏《八股消消乐》旨在记录个人所背的八股文&#xff0c;包括Java/Go开发、Vue开发、系统架构、大模型开发、具身智能、机器学习、深度学习、力扣算法等相关知识点&#xff…