Telerik生態整合:Kendo UI for Angular組件在WinForms應用中的深度嵌入(二)

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…