当前位置:   article > 正文

WinForm(十三)WebView2

winform webview2

WebView是WinForm框架中一个控件,用来对网页信息交互,有时Web自己开发的,有时Web是三方的。

下面通过一个例子来看看WebView2的使用。

首先看Web的逻辑,是一个商品添加页面,用AlpineJS和BootStrap来开发的,业务上点击添加按钮,弹出modal框窗,然后保存结果,完成添加,代码如下:

View

  1. @{
  2. ViewData["Title"] = "商品管理";
  3. }
  4. @section Css{
  5. <style>
  6. .form-switch {
  7. display: flex !important;
  8. flex-direction: row-reverse !important;
  9. justify-content: space-between !important;
  10. }
  11. </style>
  12. }
  13. <div x-data="querydata()" id="ttt">
  14. <div class="row" style="margin:4px">
  15. <div class="col-sm-4">
  16. </div>
  17. <div class="col-sm-4">
  18.         </div>
  19. <div class="col-sm-4" style="text-align:right" style="margin:4px 0px">
  20. <button type="button" class="btn btn-info" data-bs-toggle="modal" data-bs-target="#addgoods">
  21. 追加
  22. </button>
  23. </div>
  24. </div>
  25. <hr />
  26. <div class="mb-3 row">
  27. <table class="table table-striped">
  28. <thead>
  29. <tr>
  30. <th>ID</th>
  31. <th>名前</th>
  32. <th>価格</th>
  33. <th>説明</th>
  34. <th>有効</th>
  35. <th>シリアル番号</th>
  36. <th>製品タイプ</th>
  37. <th>操作</th>
  38. </tr>
  39. </thead>
  40. <tbody>
  41. <template x-for="goods in Goodses">
  42. <tr>
  43. <td x-text="goods.ID"></td>
  44. <td x-text="goods.Name"></td>
  45. <td x-text="goods.Price"></td>
  46. <td x-text="goods.Describe"></td>
  47. <td x-text="goods.Validate"></td>
  48. <td x-text="goods.SerialNumber"> </td>
  49. <td x-text="goods.GoodsType"></td>
  50. <td>
  51. <button type="button" class="btn btn-primary btn-sm" data-bs-toggle="modal" data-bs-target="#modifygoods" x-on:click="modify(goods)">改訂</button>
  52. <button type="button" class="btn btn-danger btn-sm" x-on:click="remove(goods.ID)">消去</button>
  53. </td>
  54. </tr>
  55. </template>
  56. </tbody>
  57.         </table>
  58.     </div>
  59. <div class="modal fade" id="addgoods" data-bs-backdrop="static" data-bs-keyboard="false" tabindex="-1" aria-labelledby="staticBackdropLabel" aria-hidden="true">
  60. <div class="modal-dialog">
  61. <div class="modal-content">
  62. <div class="modal-header">
  63. <h5 class="modal-title" id="staticBackdropLabel"> 追加Goods</h5>
  64. <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
  65. </div>
  66. <div class="modal-body">
  67. <div class="container-fluid">
  68. <div class="mb-3 row">
  69. <label for="GoodsTypeID" class="col-sm-4 col-form-label">Goodsタイプ</label>
  70. <div class="col-sm-8">
  71. <select class="form-select" x-model="Goods.GoodsTypeID" id="GoodsTypeID" aria-label="Default select example">
  72. <option selected>製品タイプ</option>
  73. <template x-for="(item,index) in GoodsTypes" :key="index">
  74. <option x-text="item.Name" :value="item.ID"></option>
  75. </template>
  76. </select>
  77. </div>
  78. </div>
  79. <div class="mb-3 row">
  80. <label for="name" class="col-sm-4 col-form-label">お名前</label>
  81. <div class="col-sm-8">
  82. <input type="text" class="form-control" x-model="Goods.Name" placeholder="" id="Name">
  83. </div>
  84. </div>
  85. <div class="mb-3 row">
  86. <label for="Price" class="col-sm-4 col-form-label">価格</label>
  87. <div class="col-sm-8">
  88. <input type="number" class="form-control" x-model="Goods.Price" placeholder="" min="1" id="Price">
  89. </div>
  90. </div>
  91. <div class="mb-3 row">
  92. <label for="Describe" class="col-sm-4 col-form-label">説明</label>
  93. <div class="col-sm-8">
  94. <input type="text" class="form-control" x-model="Goods.Describe" placeholder="" min="1" id="Describe">
  95. </div>
  96. </div>
  97. <div class="mb-3 row">
  98. <label for="SerialNumber" class="col-sm-4 col-form-label">シリアル番号</label>
  99. <div class="col-sm-8">
  100. <input type="number" class="form-control" x-model="Goods.SerialNumber" placeholder="" min="1" id="SerialNumber">
  101. </div>
  102. </div>
  103. <div class="form-check form-switch mb-3 row" style="margin-left:150px">
  104. <label class="form-check-label" for="IsCollapse">有効</label>
  105. <input class="form-check-input" type="checkbox" role="switch" x-model="Goods.Validate" id="Validate" checked>
  106. </div>
  107. <div></div>
  108. </div>
  109. <div class="modal-footer">
  110. <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">閉鎖</button>
  111. <button type="button" class="btn btn-primary" data-bs-dismiss="modal" x-on:click="sava">保存</button>
  112. </div>
  113. </div>
  114. </div>
  115. </div>
  116.     </div>
  117. @section Scripts{
  118. <script src="~/js/Alpine.js" defer></script>
  119.         <script>
  120. function querydata() {
  121. return {
  122. GoodsTypes: [],
  123. Goodses: [],
  124. Goods: {
  125. Name: '',
  126. Price: 0,
  127. Describe: '',
  128. Validate: true,
  129. SerialNumber: 0,
  130. GoodsTypeID: 0,
  131. GoodsType: '',
  132.                     },
  133. init() {
  134. that = this
  135. $.get("/home/goodses", {}, function (data) {
  136. if (data != null) {
  137. that.GoodsTypes = data.Data.GoodsTypes
  138. that.Goodses = data.Data.Goodses
  139. } else {
  140. console.log("/Home/Goodses is error")
  141. }
  142. });
  143. },
  144. sava() {
  145. $.ajax({
  146. type: "POST",
  147. url: "/home/goods",
  148. data: this.Goods,
  149. success: function (data) {
  150. if (data.Result) {
  151. alert("送信に成功!")
  152. that.init()
  153. that.Goods = {
  154. Name: '',
  155. Price: 0,
  156. Describe: '',
  157. Validate: true,
  158. SerialNumber: 0,
  159. GoodsTypeID: 0,
  160. GoodsType: '',
  161. }
  162. } else {
  163. alert("提出に失敗しました:" + data.Message)
  164. }
  165. }
  166. });
  167.                     }
  168. }
  169. }
  170. </script>
  171. }
  172. </div>

Controller

  1. using Microsoft.AspNetCore.Mvc;
  2. using System.Collections.Immutable;
  3. using System.Diagnostics;
  4. using WinFormDemo12WebHost.Models;
  5. namespace WinFormDemo12WebHost.Controllers
  6. {
  7. public class HomeController : Controller
  8. {
  9. private readonly ILogger<HomeController> _logger;
  10. public HomeController(ILogger<HomeController> logger)
  11. {
  12. _logger = logger;
  13.         }
  14.         public IActionResult Goods()
  15. {
  16. return View();
  17. }
  18. static List<GoodsType> _goodsTypes = new List<GoodsType> {
  19. new GoodsType {ID=1,Name="A类型" },
  20. new GoodsType {ID=2,Name="B类型" },
  21. };
  22. static List<Goods> _goodses = new List<Goods>
  23. {
  24. };
  25. [HttpGet("/home/goodses")]
  26. public async Task<JsonResult?> QueryGoodsesAsync()
  27. {
  28. try
  29. {
  30. _logger.LogInformation("BackQuery Goods List");
  31. var goodsTypes = _goodsTypes;
  32. var goodses = _goodses;
  33. return new JsonResult(
  34. new
  35. {
  36. Data = new
  37. {
  38. GoodsTypes = goodsTypes,
  39. Goodses = goodses
  40. }
  41. });
  42. }
  43. catch (Exception exc)
  44. {
  45. _logger.LogCritical(exc, exc.Message);
  46. return new JsonResult(new
  47. {
  48. Result = false,
  49. Message = exc.Message
  50. });
  51. }
  52. }
  53. [HttpDelete("/home/goods")]
  54. public async Task<JsonResult?> DeleteGoodsAsync(int id)
  55. {
  56. try
  57. {
  58. _logger.LogInformation("delete goods");
  59. var result = _goodses.Remove(_goodses.SingleOrDefault(s => s.ID == id));
  60. return new JsonResult(
  61. new
  62. {
  63. Result = result
  64. });
  65. }
  66. catch (Exception exc)
  67. {
  68. _logger.LogCritical(exc, exc.Message);
  69. return new JsonResult(new { Result = false, Message = exc.Message });
  70. }
  71. }
  72. [HttpPut("/home/goods")]
  73. public async Task<JsonResult?> ModifyGoodsAsync(Goods goods)
  74. {
  75. try
  76. {
  77. _logger.LogInformation("modify goods");
  78. _goodses.Remove(_goodses.SingleOrDefault(s => s.ID == goods.ID));
  79. goods.ID = _goodses.Max(s => s.ID) + 1;
  80. _goodses.Add(goods);
  81. return new JsonResult(
  82. new
  83. {
  84. Result = goods
  85. });
  86. }
  87. catch (Exception exc)
  88. {
  89. _logger.LogCritical(exc, exc.Message);
  90. return new JsonResult(new { Result = false, Message = exc.Message });
  91. }
  92. }
  93. [HttpPost("/home/goods")]
  94. public async Task<JsonResult?> AddGoodstAsync(Goods goods)
  95. {
  96. try
  97. {
  98. _logger.LogInformation("add goods");
  99. goods.ID = _goodses.Count > 0 ? _goodses.Max(s => s.ID) + 1 : 1;
  100. _goodses.Add(goods);
  101. return new JsonResult(
  102. new
  103. {
  104. Result = true,
  105. Data = goods
  106. });
  107. }
  108. catch (Exception exc)
  109. {
  110. _logger.LogCritical(exc, exc.Message);
  111. return new JsonResult(new { Result = false, Message = exc.Message });
  112. }
  113.         }   
  114. }
  115. public class GoodsType
  116. {
  117. public int ID { get; set; }
  118. public string? Name { get; set; }
  119. }
  120. public class Goods
  121. {
  122. public int ID { get; set; }
  123. public string? Name { get; set; }
  124. public decimal Price { get; set; }
  125. public string? Describe { get; set; }
  126.         public bool Validate { getset; }
  127.         public int GoodsTypeID { getset; }
  128. public int SerialNumber { get; set; }
  129. public string GoodsType { get; set; }
  130. public decimal MaxPrice
  131. {
  132. get
  133. {
  134. return Price >= 70000 ? Price + 3000 : (Price > 0 ? Price + 2000 : 0);
  135. }
  136. }
  137. public decimal MinPrice
  138. {
  139. get
  140. {
  141. return Price >= 70000 ? Price - 3000 : (Price > 2000 ? Price - 2000 : 0);
  142. }
  143. }
  144. }
  145. }

WebView2与控件与Web的交互主要通过webView21.CoreWebView2.ExecuteScriptAsync方法完成,所以不同的Web内容,JS的写法不一样,当然这里的JS实现简单交互还行,更复杂的就有点吃力了,可以使用一些UI自动化工库来操作更快捷。在WinForm中使用WebView,更多的是用来展现数据,而不是互操作,所以下面只是一个简单交互例子而已。

下面是模拟三个动作:点击添加按钮,在商品添加页面中完成信息录入,然后点击保存按钮(即使保存成功或失败后的alter也能针对处理)。

  1. using System.Collections.Generic;
  2. namespace WinFormsDemo13
  3. {
  4. public partial class Form1 : Form
  5. {
  6. public Form1()
  7. {
  8. InitializeComponent();
  9.         }
  10. private void Form1_Load(object sender, EventArgs e)
  11. {
  12. webView21.Source = new Uri(@"http://localhost:5026/home/goods");
  13.         }
  14. private void button1_Click(object sender, EventArgs e)
  15. {
  16. var js = """
  17. $(".btn-info").click()
  18. """;
  19. webView21.CoreWebView2.ExecuteScriptAsync(js);
  20. }
  21. int sn = 1;
  22. private void button2_Click(object sender, EventArgs e)
  23. {
  24. int mark = DateTime.Now.Millisecond * 1000 + DateTime.Now.Microsecond;
  25. var js = $"""
  26. var goods=document.querySelector('[x-data]')._x_dataStack[0].Goods;
  27. goods.GoodsTypeID={mark % 2 + 1};
  28. goods.Name="商品{mark}";
  29. goods.Price={100 * new Random().Next(1, 20)};
  30. goods.Describe="商品{mark}说明";
  31. goods.SerialNumber={sn};
  32. goods.Validate={(mark % 2 == 0).ToString().ToLower()};
  33. goods.GoodsType="{(mark % 2 == 0 ? "A类型" : "B类型")}";
  34. """;
  35. webView21.CoreWebView2.ExecuteScriptAsync(js);
  36. sn++;
  37. }
  38. private void button3_Click(object sender, EventArgs e)
  39. {
  40. var js = """
  41. $("#addgoods .btn-primary").click()
  42. """;
  43. webView21.CoreWebView2.ExecuteScriptAsync(js);
  44. }
  45. private void CoreWebView2_ScriptDialogOpening(object? sender, Microsoft.Web.WebView2.Core.CoreWebView2ScriptDialogOpeningEventArgs e)
  46. {
  47. e.Accept();
  48. }
  49. private void webView21_CoreWebView2InitializationCompleted(object sender, Microsoft.Web.WebView2.Core.CoreWebView2InitializationCompletedEventArgs e)
  50. {
  51. if (e.IsSuccess)
  52. {
  53. webView21.CoreWebView2.Settings.AreDefaultScriptDialogsEnabled = false;
  54. webView21.CoreWebView2.ScriptDialogOpening += CoreWebView2_ScriptDialogOpening;
  55. }
  56. }
  57. }
  58. }

运行结果:

803d6b66da9fd36035e8f5b21b266fbe.png

技术群:添加小编微信并备注进群

小编微信:mm1552923   

公众号:dotNet编程大全    

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/凡人多烦事01/article/detail/700429
推荐阅读
  

闽ICP备14008679号