在 Blazor Hybrid 应用中,
Razor 组件在设备上本机运行。 组件通过本地互操作通道呈现到嵌入式 Web View 控件。 组件不在浏览器中运行,并且不涉及 WebAssembly。 Razor 组件可快速加载和执行代码,组件可通过 .NET 平台完全访问设备的本机功能。 Web View 中呈现的组件样式与平台相关,可能需要你使用自定义样式表来说明不同平台之间的呈现差异。
如何在Blazor Hybrid中读取本地图片展示?
在Blazor Hybrid经常遇到一些读取选中的图片并且渲染,但是文件的目录在Blazor中直接src填写是无法读取到的,这个时候就可能需要将文件Copy到wwwroot中,或者将其转换Base64放入到html中,但是base64转换图片是很长的一串字符串,这样可能会导致渲染可能卡扽,所以我们将使用js提供的功能去实现,其实在Blazor Hybrid为了兼容,可以采用js提供的部分功能实现,效果更好,
创建一个`Winform`项目
示图:
添加 `Microsoft.AspNetCore.Components.WebView.WindowsForms`NuGet包
dotnet add package Microsoft.AspNetCore.Components.WebView.WindowsForms
修改项目文件的属性
打开`BlazorHybrid.csproj`项目文件,将`Microsoft.NET.Sdk` 修改成`Microsoft.NET.Sdk.Razor`
<ProjectSdk="Microsoft.NET.Sdk.Razor">
创建 `_Imports.razor`文件,添加以下代码
Microsoft.AspNetCore.Components.WebMicrosoft.AspNetCore.Components.Routing
创建`wwwroot`文件夹
创建`wwwroot/index.html`文件,添加以下代码
<htmllang="en"><head><metacharset="utf-8"/><metaname="viewport"content="width=device-width, initial-scale=1.0"/><title>WinFormsBlazor</title><basehref="/"/><linkhref="css/app.css"rel="stylesheet"/><linkhref="WinFormsBlazor.styles.css"rel="stylesheet"/></head><body><divid="app">加载中...</div><divid="blazor-error-ui"> An unhandled error has occurred. <ahref=""class="reload">Reload</a><aclass="dismiss">🗙</a></div><!--引用blazor.webview.js Server和web assembly,hybrid的js都不一样--><scriptsrc="_framework/blazor.webview.js"></script></body></html>``` 创建`wwwroot/css/app.css`添加以下代码 ```css html, body { font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; } h1:focus { outline: none; } a, .btn-link { color: #0071c1; } .btn-primary { color: #fff; background-color: #1b6ec2; border-color: #1861ac; } .valid.modified:not([type=checkbox]) { outline: 1px solid #26b050; } .invalid { outline: 1px solid red; } .validation-message { color: red; } #blazor-error-ui { background: lightyellow; bottom: 0; box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2); display: none; left: 0; padding: 0.6rem 1.25rem 0.7rem 1.25rem; position: fixed; width: 100%; z-index: 1000; } #blazor-error-ui .dismiss { cursor: pointer; position: absolute; right: 0.75rem; top: 0.5rem; }
创建`Shared/App.razor`添加以下代码
<RouterAppAssembly="@typeof(MainLayout).Assembly"><FoundContext="routeData"><RouteViewRouteData="@routeData"DefaultLayout="@typeof(MainLayout)"/><FocusOnNavigateRouteData="@routeData"Selector="h1"/></Found><NotFound><PageTitle>Not found</PageTitle><LayoutViewLayout="@typeof(MainLayout)"><prole="alert">Sorry, there's nothing at this address.</p></LayoutView></NotFound></Router>
创建`Shared/MainLayout.razor`添加以下代码
@inherits LayoutComponentBase <div> @Body </div>
选择`Form1.cs`打开设计窗口,将`BlazorWebView`拖到Form1中,并且将`BlazorWebView`的属性中的`Dock`修改成`Fill`
将以下命名空间添加到Form1.cs文件的顶部
usingMicrosoft.AspNetCore.Components.WebView.WindowsForms; usingMicrosoft.Extensions.DependencyInjection;
在 `Form1` 构造函数中的 `InitializeComponent` 方法调用后面,添加以下代码:
varservices=newServiceCollection(); services.AddWindowsFormsBlazorWebView(); blazorWebView1.HostPage="wwwroot\\index.html"; blazorWebView1.Services=services.BuildServiceProvider(); blazorWebView1.RootComponents.Add<App>("#app");
效果如图
修改`wwwroot/index.html`代码。添加js方法,将以下代码添加到`body`里面
<script>/** 将byte转url对象 */functionbyteToUrl(blob) { // 适配webview和web varmyBlob=newBlob([blob], { type: "image/png" }); return (window.URL||window.webkitURL||window|| {}).createObjectURL(myBlob); } /** * 释放url对象,因为createObjectURL创建的对象一直会存在可能会占用过多的内存,请注意释放 */functionrevokeUrl(url) { (window.URL||window.webkitURL||window|| {}).revokeObjectURL(url); } </script>
创建`Pages/Index.razor`文件,并添加以下代码
@using Microsoft.JSInterop; @inject IJSRuntime JSRuntime @page "/" @if (!string.IsNullOrEmpty(Img)){ <imgsrc="@Img"/>} <input@bind="ImgPath"/><button@onclick="OnLoad">加载图片</button><button@onclick="Revoke">释放图片</button>@code { public string? ImgPath { get; set; } private string? Img; private async Task OnLoad() { // 加载目录中的图片获取到byte 通过byteToUrl转换URL对象 可以直接通过url获取到图片 它存在与本地 var file = await File.ReadAllBytesAsync(ImgPath); Img = await JSRuntime.InvokeAsync<string>("byteToUrl", file); } private async Task Revoke() { if (!string.IsNullOrEmpty(Img)){ await JSRuntime.InvokeVoidAsync("revokeUrl", Img); Img = string.Empty; } } } <style>button { background-color: cornflowerblue; height: 30px; font-size: 15px; width: auto; } img{ height:auto; width:auto; } </style>
最终效果:
结尾
我们可以通过`createObjectURL`加载本地文件或者图片,并且渲染,这样对比copy到`wwwroot`或者转换`base64`的效果更好,而且更容易管理,实现也超级容易,用于跨平台实现也算是最佳实现了,
`Blazor`技术交流:452761192
来自token的分享