当前位置: 首页 > news >正文

【项目实战】如何将接口传过来的html文件通过WPF控件展示在桌面应用程序?

一、核心控件

<WebBrowser />

二、创建页面
<Window x:Class="WPF.HtmlViewerWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:WPF" mc:Ignorable="d" Title="HtmlViewerWindow" Height="450" Width="800"> <WebBrowser x:Name="WebBrowserControl"/> </Window>
三、实现构造函数
public HtmlViewerWindow(string htmlContent) { InitializeComponent(); Loaded += (s, e) => { string projectResourcesPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory,"Resources","resources"); string absoluteResourcesPath = projectResourcesPath.Replace("\\","/"); string correctedHtml = htmlContent.Replace("../resource/", $"file:///{absoluteResourcesPath}/"); WebBrowserControl.NavigateToString(correctedHtml); }; }

Comment:

InitializeComponent(); //IDE自动生成的方法,负责初始化控件;

Loaded += (s,e) => {.....}; //控件加载事件的绑定,后面是Lambda表达式绑定一个匿名方法;

Path.Combine(.....); //路径拼接,旨在获取加载html文件时所需的资源文件;AppDomain.CurrentDomain.BaseDirectory //获取程序运行时的根目录,编译(Build)的时候会将项目里的Resource文件夹放进程序运行时的根目录;

"Resources","resources" //html文件的资源文件是resources,但是作者在项目下单独建了一个Resources文件夹用来统一存放各种资源;

projectResourcesPath.Replace("\\","/"); //Windows路径用反斜杠\,但URL格式用正斜杠/,所以需要替换从而避免转义问题;

htmlContent.Replace("../resource/", $"file:///{absoluteResourcesPath}/"); //将html里的相对资源路径(../resource/)替换为之前定义的绝对路径(file:///{absoluteResourcesPath}/),从而让WebBrowser能找到资源里的图片样式等资源,下图就是我的html里相对资源路径的普遍应用,所以作者得替换掉,不然找不到资源。这部分仅供参考,具体还需看读者自己的html文件里的资源路径。​

WebBrowserControl.NavigateToString(correctedHtml); //调用WebBrowser控件的NavigateToString()方法,让处理过的html字符串加载到控件上进行展示。

四、创建公共方法,处理html文件,调用页面
public void OpenHtmlFile(byte[] target) { try { if (target != null && !string.IsNullOrEmpty(Encoding.UTF8.GetString(target))) { string htmlFilePath = string.Empty; string preliminaryContextAfterUTF8 = Encoding.UTF8.GetString(target); try { byte[] base64ReportBytes = Convert.FromBase64String(preliminaryContextAfterUTF8); htmlFilePath = Encoding.UTF8.GetString(base64ReportBytes); } catch (FormatException) { htmlFilePath = preliminaryContextAfterUTF8; } WFSCommonHelper.ShowHtmlFilePopup(htmlFilePath); } else { MessageBox.Show("HtmlFileNotFound","Error",MessageBoxButton.OK,MessageBoxImage.Error); } } catch (Exception ex) { Exception ext; ExceptionHandler.HandleException(ex, ExceptionHandlingPolicy.UiPolicy, out ext, GetContext()); //自定义异常处理器 } }

Comment:

由于作者这里会调用两个接口传过来的html文件,并且两个接口传过来的html的编码类型不一样,一种是原生文本UTF-8字节类型,另一种是Base64编码中转字节类型,这两种类型经过初步UTF-8解码之后有各自的核心特征,第一种用VS的可视化器打开就能看见<html>/<!DOCTYPE>等明文标签,第二种只能看见开头为PCFET0NUWVBF的规律字符,所以处理字节流就有两种方式:

首先对字节流进行初步的UTF-8解码,然后执行如下操作:

1.尝试将初步UTF-8解码对象再次进行Base64解码得到原始的html的UTF-8数组,如果未发生异常,证明从接口传过来的是Base64编码中转字节类型,就再执行一次UTF-8解码。

2.如果进行Base64解码的时候发生了异常,就证明从接口传过来的是原生文本UTF-8字节类型,只需要一次UTF-8解码。

经过上面解码操作之后,就能得到完整的html的字符串,然后传给自定义的WFSCommonHelper里的ShowHtmlFilePopup方法。此方法用来打开最初定义的页面,并设置初始位置、页面大小。具体实现如下:

public static void ShowHtmlFilePopup(string htmlFilePath) { Popup popup = new Popup(); var control = new HtmlViewerWindow(htmlFilePath); popup.WindowStartupLocation = WindowStartupLocation.CenterScreen; popup.ShowPopup(control, 1250, 765); }

效果图:

Tips:作者定义单独方法来打开HtmlViewWindow页面是因为项目代码架构是这样规定的,需要跟架构一致,读者可以将HtmlViewWindow的partial类继承至Window类,然后可以定义一个HtmlViewWindow的对象,并把html字符串传给此对象的实例,最后调用此对象的Show()方法也可达到类似效果。所以具体问题具体分析,若有错误,欢迎读者在评论区指出。

http://www.jsqmd.com/news/474893/

相关文章:

  • 用Unity物理引擎还原真实赛车手感:齿轮变速+悬挂系统调试指南
  • 高德地图JSAPI实战:如何给北京市各区自定义颜色标记(附完整代码)
  • 基于Docker与macvlan:在Linux服务器上构建高性能OpenWrt软路由
  • MedGemma X-Ray开发者案例:gradio_app.py与Orthanc PACS双向DICOM通信
  • ESP32-C2技术文档体系与工程落地全链路指南
  • 多线程并发处理样例
  • 设计模式的六大原则:原理与实践
  • ESP32-C61总线与内存访问监控系统深度解析
  • ComicAI vs 传统漫画制作:实测AI生成30页漫画要花多少法力值?
  • OpenCV实战:SIFT特征提取在图像匹配中的关键应用
  • 简单使用Linux
  • STM32L1调试控制与设备电子签名深度解析
  • Oracle【实战指南】19c ADG容灾配置与同步模式深度解析
  • 避坑指南:Spring Data Redis 2.6.2升级后GEO功能失效的解决方案
  • Unity 2021.3.6f1项目实战:HybridCLR热更新从零配置到避坑指南
  • 零基础玩转Image-to-Video:手把手教你一键生成动态视频
  • 议程公布 | 智能车载音频专题论坛将于3月25-26日举办
  • 《Kubernetes故障篇: kubelet 证书实现自动续签》
  • Qwen3-8B惊艳案例:生成创意故事和复杂逻辑推理实测
  • 《QGIS快速入门与应用基础》216:项目→布局管理器
  • Linux - 基础IO【下】
  • UR机器人通信端口全解析:从Modbus TCP到Dashboard的实战避坑指南
  • 云容笔谈解决403 Forbidden错误:API访问权限与配置详解
  • JavaScript 设计模式分类与应用实践
  • Markdown中同时使用了TOC与HTML锚点后,锚点无效解决方法
  • 通义千问1.5-1.8B-Chat-GPTQ-Int4实战:自动化作业批改与个性化反馈生成
  • 2026年洗车槽生产厂家盘点!钢制洗车槽厂家/工地洗车池厂家推荐/洗车槽租赁推荐/工地洗车槽厂家推荐:宁波玖鼎领衔 - 栗子测评
  • 5分钟搞定Arduino IDE+ESP32开发环境(最新2.0.9版)
  • 当水泥浆遇上随机裂隙:COMSOL里的流动艺术
  • 2026年知名的增强剂公司推荐:防水增强剂直销厂家推荐 - 品牌宣传支持者