在Blazor中构建数据库应用程序——第4部分——UI控件

本文是关于使用Blazor构建数据库应用程序系列的第四部分,重点介绍了UI组件的构建,包括RouteViews、表单和自定义控件如UIButton、UIColumn等。文章展示了如何从HTML和CSS构建可复用的UI组件,以及如何在实际应用中使用这些组件来创建CRUD操作的视图和表单。
摘要由CSDN通过智能技术生成

目录

介绍

存储库和数据库

组件

RouteViews

表单

UI控件

UIBase

一些例子

UIButton

UIColumn

UILoader

UIContainer/UIRow/UIColumn

总结


介绍

本文是构建Blazor数据库应用程序系列文章中的第四篇。本文着眼于我们在UI中使用的组件,然后重点介绍如何从HTMLCSS构建通用UI组件。

  1. 项目结构和框架——一些介绍。
  2. 服务——构建CRUD数据层。
  3. 查看组件——UI中的CRUD编辑和查看操作。
  4. UI组件——构建 HTML/CSS控件。
  5. 查看组件——UI中的CRUD列表操作。

存储库和数据库

文章的存储库已移至CEC.Blazor.SPA存储库   CEC.Blazor GitHub存储库已过时,将被删除。

存储库中的/SQL中有一个用于构建数据库的SQL脚本。

您可以在同一站点上看到在此处运行的项目的Server和WASM版本

组件

要详细了解组件,请阅读我的文章深入了解 Blazor 组件

Blazor UI中的所有内容(起始页除外)都是一个组件。是的,应用程序、路由器……它们都是组件。并非所有组件都发出Html

您可以将组件分为四类:

  1. RouteViews ——这些是顶级组件。视图与布局相结合以形成显示窗口。
  2. Layouts——布局与视图结合构成显示窗口。
  3. Forms——表单是控件的逻辑集合。编辑表单、显示表单、列表表单、数据录入向导都是经典的表单。表单包含控件——不是HTML
  4. Controls——控件要么显示某些内容——发出 HTML——要么执行某些工作单元。文本框、下拉菜单、按钮、网格都是经典的Hrtml发射控件。应用程序、路由器、验证是执行工作单元的控件。

RouteViews

RouteViews是特定于应用程序的,RouteViewForm之间的唯一区别是RouteView通过@Page指令声明一个或多个路由。在根App中声明的Router组件将设置为一个特定的代码程序集AppAssembly。这是Router在启动时搜索所有声明路由的程序集。

在应用程序中,RouteViews被声明在WASM应用程序库中。  

天气预报查看器和列表视图如下所示。

// Blazor.Database/RouteViews/Weather/WeatherViewer.cs
@page "/weather/view/{ID:int}"

<WeatherForecastViewerForm ID="this.ID" ExitAction="this.ExitToList"></WeatherForecastViewerForm>

@code {
    [Parameter] public int ID { get; set; }

    [Inject] public NavigationManager NavManager { get; set; }

    private void ExitToList()
        => this.NavManager.NavigateTo("/fetchdata");
}
// Blazor.Database/RouteViews/Weather/FetchData.cs
@page "/fetchdata"

<WeatherForecastComponent></WeatherForecastComponent>

表单

我们在上一篇文章中看到了表单。它们特定于应用程序。

下面的代码显示了天气查看器。都是UI控件,没有HTML标记。

// Blazor.Database/Components/Forms/WeatherForecastViewerForm.razor
@namespace Blazor.Database.Components
@inherits RecordFormBase<WeatherForecast>

<UIContainer>
    <UIFormRow>
        <UIColumn>
            <h2>Weather Forecast Viewer</h2>
        </UIColumn>
    </UIFormRow>
</UIContainer>
<UILoader Loaded="this.IsLoaded">
    <UIContainer>
        <UIFormRow>
            <UILabelColumn>
                Date
            </UILabelColumn>
            <UIInputColumn Cols="3">
                <InputReadOnlyText Value="@this.ControllerService.Record.Date.ToShortDateString()"></InputReadOnlyText>
            </UIInputColumn>
            <UIColumn Cols="7"></UIColumn>
        </UIFormRow>
        <UIFormRow>
            <UILabelColumn>
                Temperature °C
            </UILabelColumn>
            <UIInputColumn Cols="2">
                <InputReadOnlyText Value="@this.ControllerService.Record.TemperatureC.ToString()"></InputReadOnlyText>
            </UIInputColumn>
            <UIColumn Cols="8"></UIColumn>
        </UIFormRow>
        <UIFormRow>
            <UILabelColumn>
                Temperature °f
            </UILabelColumn>
            <UIInputColumn Cols="2">
                <InputReadOnlyText Value="@this.ControllerService.Record.TemperatureF.ToString()"></InputReadOnlyText>
            </UIInputColumn>
            <UIColumn Cols="8"></UIColumn>
        </UIFormRow>
        <UIFormRow>
            <UILabelColumn>
                Summary
            </UILabelColumn>
            <UIInputColumn Cols="9">
                <InputReadOnlyText Value="@this.ControllerService.Record.Summary"></InputReadOnlyText>
            </UIInputColumn>
        </UIFormRow>
    </UIContainer>
</UILoader>
<UIContainer>
    <UIFormRow>
        <UIButtonColumn>
            <UIButton AdditionalClasses="btn-secondary" ClickEvent="this.Exit">Exit</UIButton>
        </UIButtonColumn>
    </UIFormRow>
</UIContainer>

页面背后的代码相对简单——复杂的是父类中的样板代码。它加载记录特定的控制器服务。

// Blazor.Database/Components/Forms/WeatherForecastViewerForm.razor.cs
public partial class WeatherForecastViewerForm : RecordFormBase<WeatherForecast>
{

    [Inject] private WeatherForecastControllerService ControllerService { get; set; }

    protected async override Task OnInitializedAsync()
    {
        this.Service = this.ControllerService;
        await base.OnInitializedAsync();
    }
}

UI控件

UI控件发出HTMLCSS标记。这里的所有控件都基于Bootstrap CSS框架。所有控件都继承自ComponentBaseUI控件继承自UIBase

UIBase

UIBase继承自Component 。它构建了一个可以打开或关闭的HTML DIV块。

让我们详细看一些UIBase

可以使用Tag参数设置HTML块标记。它只能由继承的类设置。

protected virtual string HtmlTag => "div";

控件CSS类是使用CssBuilder类构建的。继承类可以设置一个主要的Css值并添加他们想要的任意数量的次要值。添加CSS类可以通过AdditionalClasses参数或通过定义class属性来添加。

[Parameter] public virtual string AdditionalClasses { get; set; } = string.Empty;
protected virtual string PrimaryClass => string.Empty;
protected List<string> SecondaryClass { get; private set; } = new List<string>();

protected string CssClass
=> CSSBuilder.Class(this.PrimaryClass)
    .AddClass(SecondaryClass)
    .AddClass(AdditionalClasses)
    .AddClassFromAttributes(this.UserAttributes)
    .Build();

可以使用两个参数隐藏或禁用该控件。当Show为真时显示ChildContent。如果Show是假则显示HideContent,如果它不是null,否则什么也不显示。

[Parameter] public bool Show { get; set; } = true;
[Parameter] public bool Disabled { get; set; } = false;
[Parameter] public RenderFragment ChildContent { get; set; }
[Parameter] public RenderFragment HideContent { get; set; }

最后,控件捕获任何附加属性并将它们添加到标记元素中。

[Parameter(CaptureUnmatchedValues = true)] public IReadOnlyDictionary<string, object> UserAttributes { get; set; } = new Dictionary<string, object>();

该控件构建输入RenderTree代码。

protected override void BuildRenderTree(RenderTreeBuilder builder)
{
    if (this.Show)
    {
        builder.OpenElement(0, this.HtmlTag);
        if (!string.IsNullOrWhiteSpace(this.CssClass)) builder.AddAttribute(1, "class", this.CssClass);
        if (Disabled) builder.AddAttribute(2, "disabled");
        builder.AddMultipleAttributes(3, this.UserAttributes);
        if (this.ChildContent != null) builder.AddContent(4, ChildContent);
        else if (this.HideContent != null) builder.AddContent(5, HideContent);
        builder.CloseElement();
    }
}

一些例子

本文的其余部分将更详细地介绍一些UI控件。

UIButton

这是一个标准的Bootstrap按钮。  

  1. Type设置按钮类型。
  2. PrimaryClass 设置。
  3. ButtonClick 处理按钮单击事件并调用EventCallback
  4. ShowDisabled处理按钮状态。

// Blazor.SPA/Components/UIComponents/Base/UIButtons.cs
@namespace Blazor.SPA.Components
@inherits UIBase
@if (this.Show)
{
    <button class="@this.CssClass" @onclick="ButtonClick" type="@Type" disabled="@this.Disabled" @attributes="UserAttributes">
        @this.ChildContent
    </button>
}
@code {
    [Parameter] public string Type { get; set; } = "button";
    [Parameter] public EventCallback<MouseEventArgs> ClickEvent { get; set; }
    protected override string PrimaryClass => "btn mr-1";
    protected async Task ButtonClick(MouseEventArgs e) => await this.ClickEvent.InvokeAsync(e);
}

下面是一些显示正在使用的控件的代码。

<UIButton Show="true" Disabled="this._dirtyExit" AdditionalClasses="btn-dark" ClickEvent="() => this.Exit()">Exit</UIButton>

UIColumn

这是一个标准的Bootstrap列。  

  1. Cols 定义列数
  2. PrimaryCss是从Cols构建的。
  3. Base RenderTreeBuilder将控件构建为div  

// Blazor.SPA/Components/UIControls/Base/UIColumn.cs
public class UIColumn : UIBase
{
    [Parameter] public virtual int Cols { get; set; } = 0;
    protected override string PrimaryClass => this.Cols > 0 ? $"col-{this.Cols}" : $"col";
}

UILoader

这是一个包装控件,旨在保存在子内容中实现错误检查。它仅在IsLoaded true时呈现其子内容。该控件节省了在子内容中实现大量错误检查。

@namespace Blazor.SPA.Components
@inherits UIBase

@if (this.Loaded)
{
    @this.ChildContent
}
else
{
    <div>Loading....</div>
}

@code {
    [Parameter] public bool Loaded { get; set; }
}

您可以在编辑查看表单中看到正在使用的控件。

UIContainer/UIRow/UIColumn

这些控件通过使用正确的Css构建DIV来创建BootStrap网格系统——即容器、行和列。

public class UIContainer : UIBase
{
    protected override string PrimaryClass => "container-fluid";
}

class UIRow : UIBase
{
    protected override string PrimaryClass => "row";
}

public class UIColumn : UIBase
{
    [Parameter] public virtual int Cols { get; set; } = 0;
    protected override string PrimaryClass => this.Cols > 0 ? $"col-{this.Cols}" : $"col";
}
// CEC.Blazor/Components/UIControls/UIBootstrapContainer/UILabelColumn.cs
public class UILabelColumn : UIColumn
{
    protected override string _BaseCss => $"col-{Columns} col-form-label";
}

下面是一些显示正在使用的控件的代码。

<UIContainer>
    <UIRow>
        <UILabelColumn Columns="2">
            Date
        </UILabelColumn>
        ............
    </UIRow>
..........
</UIContainer>

总结

本文概述了如何使用组件构建UI控件,并详细研究了一些示例组件。你可以在GitHub Repository中看到所有的库UIControls

需要注意的一些关键点:

  1. UI控件使您可以从更高级别的组件(例如表单和视图)中抽象标记。
  2. UI控件为您提供控制权,并对HTMLCSS标记应用一些规则。
  3. ViewForm组件更清晰、更易于查看。
  4. 使用尽可能少或尽可能多的抽象。
  5. 控件,例如UILoader,让生活更轻松!

如果您在未来阅读本文,请查看存储库中的自述文件以获取文章集的最新版本。

https://www.codeproject.com/Articles/5280090/Building-a-Database-Application-in-Blazor-Part-4-U

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值