Day 06 抽离C#程序码

昨天看到FetchData.razor的程序太长了,截图都要两次,为求方便,我们把@code的部分撷取出来另成一个档案。

Blazor提供了两个方法:partial classComponentBase,同样两者各有优缺点,笔者偏好ComponentBase,端看个人使用习惯。

先来看partial class,我们打开FetchData.razor,把前面提到的@using BlazorServer.Data移到_Imports.razor,再建立一个class叫做FetchData.razor.cs,在publicclass中间加上partial修饰词,接着把FetchData.razor的@code区块剪下贴到FetchData.razor.cs後稍作修改,可以看出跟旧的C#程序没什麽差别。我们按下F5,一样看到10笔天气资料。
https://ithelp.ithome.com.tw/upload/images/20210906/20140893EsdlPOlaqT.png
https://ithelp.ithome.com.tw/upload/images/20210906/201408936GuVa31ssx.png
https://ithelp.ithome.com.tw/upload/images/20210906/201408939r92PSfFzf.png

接着来看ComponentBase,先把partial class里面的程序复制下来,接着建立一个新class取名为FetchDataBase.cs,将刚刚的程序贴上後稍做修改,再删除FetchData.razor.cs这个partial class,因为两种模式不能并存。可以看到除了继承ComponentBase跟加上[Inject]外,几乎没有差别,这里的[Inject]相当於在FetchData.razor.cs使用@inject WeatherForecastService ForecastService,我们按下F5启动侦错模式,在20行左边按一下设定中断点,可以看到一样取得了天气资料。
https://ithelp.ithome.com.tw/upload/images/20210906/201408932rrbHtxNQP.png
https://ithelp.ithome.com.tw/upload/images/20210906/20140893gzBNseVh8v.png

接着开始做自己的Component吧!先将不必要的Component删除,Startup.cs_Import.razor里面跟天气有关的using及注册同样删除,如果忘记这两个档案在哪里,可以在删除Component後将滑鼠移到专案BlazorServer点右键,选取重建专案,Visual Studio就会告诉你哪里出错了。
https://ithelp.ithome.com.tw/upload/images/20210906/20140893q5ZQ401wSW.png

之前说过要完成让使用者写日志的网站,所以需要最基本的输入框,而日志的单位就以一篇计算。首先建立Models资料夹,建立PostModel类别,里面很简单只有3个属性,接着在Pages资料夹建立Post.razorPostBase.razor.cs,最後将NavMenu.razor的连结留下一个,href属性的值改为Post
https://ithelp.ithome.com.tw/upload/images/20210906/20140893jDwwQxJynJ.png

PostModel是用来承接资料的容器,目前没有Service,所以在PostBase.razor.cs放一笔假资料,这边可以看到一个方法OnInitializedAsync(),代表当这个Component生命周期伊始,里面的事情就会先做,其他还有OnAfterRenderAsyncOnParametersSetAsync等等,只要先输入override再按一下空白键,就可以看到这些方法,且也有同步跟非同步两种模式,这些方法有机会再说明。
https://ithelp.ithome.com.tw/upload/images/20210906/20140893HbFSeYANaz.png
https://ithelp.ithome.com.tw/upload/images/20210906/20140893FwTKkUVHBb.png

Post.razor用了EditForm这个Component,编译过後相当於html的form元素,里面还有3个input元素,Blazor也有提供相对应的Input Component,可以从官方文件看到分别编译後的html元素。
https://ithelp.ithome.com.tw/upload/images/20210906/20140893xJTQ4iPLP4.png
https://ithelp.ithome.com.tw/upload/images/20210906/20140893ORHFU4dgH1.png
https://ithelp.ithome.com.tw/upload/images/20210906/20140893dDQipT6IWx.png

这时候打开网页来看,可以看到上面出现了我们定义在PostBase.razor.cs的值,但这是怎麽连结起来的呢?原因就是EditForm的Model属性及3个<Input> Component的属性@bind-Value,这里在告诉Blazor:我的Model跟里面的值要跟这个EditForm绑在一起,如果这里有跟後端程序连结,网页上输入的内容经过事件触发後,就会送到後端处理。
https://ithelp.ithome.com.tw/upload/images/20210906/201408935Ubl5EphCa.png

不过<Input>预设的CSS样式不太好看,我们先套用基本的boostrap样式;因为Id通常不会让使用者输入,所以这边先注解,然後再加入表格验证机制,毕竟不能让使用者随便输入就送出表格,但如果不想自己写一堆验证机制呢?可以试试看Blazor的DataAnnotationsValidatorValidationSummary两个Component。
https://ithelp.ithome.com.tw/upload/images/20210906/20140893tHRrhMffCJ.png
https://ithelp.ithome.com.tw/upload/images/20210906/20140893zzYfGSum4o.png

我们先在PostModelTitleContent加上两个AttributeRequired代表必填,MaxLengthMinLength则是限制最大及最小字数,还可以自订错误讯息。接着在EditForm里面加上那两个Component DataAnnotationsValidatorValidationSummary,第一个是验证个别Input,第二个则是将错误讯息显示在表格上方。
https://ithelp.ithome.com.tw/upload/images/20210906/20140893kIgO8Oe0tc.png
https://ithelp.ithome.com.tw/upload/images/20210906/20140893r2usnA9Gl7.png
https://ithelp.ithome.com.tw/upload/images/20210906/20140893KBSOVLJXw5.png

但如果不喜欢验证机制预设的CSS样式呢?Blazor也提供客制化的方法。先建立一个class名为CustomFieldClassProvider且继承FieldCssClassProvider,覆写方法GetFieldCssClass,里面的内容待会再说。
https://ithelp.ithome.com.tw/upload/images/20210906/20140893ev1K5n3h9c.png

接着在PostBase.razor.cs加入一个类别为EditContext的属性editContext,初始化产生物件editContext,将原本的Post物件丢进去建构子,然後呼叫editContext的方法SetFieldCssClassProvider,在建构子产生新CustomFieldClassProvider物件。
https://ithelp.ithome.com.tw/upload/images/20210906/20140893Rz6fcsbio9.png

最後最重要的一步,在Post.razorEditForm的Model参数移除,改为EditContext参数,里面的值就是刚刚的editContext物件。
https://ithelp.ithome.com.tw/upload/images/20210906/20140893eVu7xbjko1.png

这时候再送出表格一次,可以看到textarea的红色外框消失了,字体也变成text-danger的红色,而正确的栏位则是变成text-primary的蓝色。我们再回头看CustomFieldClassProvider,原来editContext指的就是EditForm的内容,fieldIdentifier则是个别Input,如果editContext呼叫的方法GetValidationMessages有在fieldIdentifier取得任何讯息,代表这是错误的栏位,没有则是正确栏位,这就是Blazor帮我们客制化Form的作法。
https://ithelp.ithome.com.tw/upload/images/20210906/20140893MPQlMPzxNB.png

Ref: Split HTML And C# Code In Blazor Using Either Partial Class Or ComponentBase Class
https://www.learmoreseekmore.com/2020/06/blazor-paratial-class-or-componentbase-class.html

Ref: ASP.NET Core Blazor forms and validation
https://docs.microsoft.com/en-us/aspnet/core/blazor/forms-validation?view=aspnetcore-5.0#binding-a-form

Ref: Custom validation CSS class attributes
https://docs.microsoft.com/en-us/aspnet/core/blazor/forms-validation?view=aspnetcore-5.0#custom-validation-css-class-attributes-1


<<:  做人如果没梦想,跟咸鱼有什麽区别!

>>:  5. bind, call, apply 的差异

Vue.js 从零开始:准备

前言 为了能更了解Vue的运作与观念,刚好藉由这次的铁人赛,从零开始学习,目标是写出能让刚开始接触的...

Day10 NiFi - Templates, Labels & Funnel

今天我们要讲的东西有点多,要一次讲三个,分别是 Templates, Labels & Fu...

[Day3] Practice Resources

CTF 通常会依照各种领域区分, Web 、 Reverse 、 Pwn 、 Crypto 等。而渗...

Day 26 : 案例分享(7.5) 库存与制造 - 物料需求计划及MES制造执行系统 (客制内容)

案例说明及适用场景 提供二个实务运用的客制案例 物料需求计划-透过销售订单生成制造订单後,载入预计投...

[DAY 3] _ 开发板规划补充(stm32f030)

先聊个题外话因为是第一次参加这种比赛,我从来没有这样发文过,我第一天担心很多,这30天会不会很难发文...