MAUI Blazor学习2-创建移动客户端Razor页面

 

MAUI Blazor学习2-创建移动客户端Razor页面

 

MAUI Blazor系列目录

  1. MAUI Blazor学习1-移动客户端Shell布局 - SunnyTrudeau - 博客园 (cnblogs.com)

 

 

为了适配移动客户端,还是要对页面做一下简单的布局。网上其实有一些适合移动客户端的Razor组件库,也可以拿来就用。我写一个简单的todo列表练练手,只实现功能,不考虑美观需求。

 

实现Master Detail页面

定义一个TodoItem数据类

 

public class TodoItem
{
    public int Id { get; set; }
    public string Title { get; set; } = "";
    public string Description { get; set; } = "";
    public DateTime CreatedDate { get; set; } = DateTime.Now;
    public TodoPriority Priority { get; set; } = TodoPriority.Low;
    public bool IsFinished { get; set; } = false;
}

 

编写服务类TodoService,初始化创建一些任务。

public class TodoService
{
    public readonly List<TodoItem> TodoItems = new List<TodoItem>();

    public TodoService()
    {
        for (int i = 1; i <= 20; i++)
        {
            var item = new TodoItem()
            {
                Id = i,
                Title = $"任务{i:00}",
                Description = $"学习MAUI系列-{i:00}",
                CreatedDate = (new DateTime(2023, 1, 1)).AddDays(i),
                Priority = (TodoPriority)(i % 3),
                IsFinished = false,
            };

            TodoItems.Add(item);
        }
    }

    public void AddTodo(TodoItem item)
    {
        TodoItems.Add(item);
    }

新建任务列表页面,取代天气数据页面,一行一个任务,标题+描述,左右对齐。

 

@page "/fetchdata"

@using MaBlaApp.Data
@inject TodoService MyTodoService

<ul class="list-group">
    <li class="list-group-item list-group-item-primary d-flex justify-content-between">
        <strong class="align-self-center">任务列表</strong>
        <a href="fetchdata/todoitem/create" class="btn btn-primary btn-sm">新建任务</a>
    </li>
</ul>

@if (todoItems == null)
{
    <p><em>Loading...</em></p>
}
else
{
    <div class="list-group" style="overflow:auto">
        @foreach (var todoItem in todoItems)
        {
            string url = $"fetchdata/todoitem/details/{todoItem.Id}";
            <a href=@url class="list-group-item list-group-item-action d-flex justify-content-between mb-1">
                <strong>@todoItem.Title</strong>
                <small>@todoItem.Description</small>
            </a>
        }
    </div>
}

@code {
    private List<TodoItem> todoItems;

    protected override void OnInitialized()
    {
        todoItems = MyTodoService.TodoItems;
    }

}

 

点击一行任务,跳转到该任务的详细页面

@page "/fetchdata/todoitem/details/{Id:int}"

@using MaBlaApp.Data
@inject TodoService MyTodoService
@inject IJSRuntime JSRuntime

<ul class="list-group">
    <li class="list-group-item list-group-item-primary d-flex justify-content-between">
        <strong class="align-self-center">任务详细</strong>
        <button class="btn btn-primary btn-sm" @onclick=Back>返回</button>
    </li>
</ul>

@if (todoItem is null)
{
    <p><em>任务不存在...</em></p>
}
else
{
    <ul class="list-group" style="overflow:auto">
        @foreach (var item in items)
        {
            <li class="list-group-item d-flex justify-content-between mb-1">
                <strong>@item.Key</strong>
                <small>@item.Value</small>
            </li>
        }

        <li class="list-group-item d-grid">
            <a href=@editUrl class="btn btn-warning btn-sm btn-block">修改</a>
        </li>
    </ul>
}

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

    private TodoItem todoItem;

    private Dictionary<string, string> items = new Dictionary<string, string>();

    private Dictionary<TodoPriority, string> TodoPriorityName = new Dictionary<TodoPriority, string>();

    private string editUrl;

    protected override void OnInitialized()
    {
        todoItem = MyTodoService.TodoItems.FirstOrDefault(x => x.Id == Id);

        if (todoItem is null)
            return;

        TodoPriorityName[TodoPriority.Low] = "";
        TodoPriorityName[TodoPriority.Middle] = "";
        TodoPriorityName[TodoPriority.High] = "";

        items[nameof(todoItem.Id)] = $"{todoItem.Id}";
        items[nameof(todoItem.Title)] = $"{todoItem.Title}";
        items[nameof(todoItem.Description)] = $"{todoItem.Description}";
        items[nameof(todoItem.CreatedDate)] = $"{todoItem.CreatedDate:d}";
        items[nameof(todoItem.Priority)] = TodoPriorityName[todoItem.Priority];
        items[nameof(todoItem.IsFinished)] = $"{todoItem.IsFinished}";

        editUrl = $"fetchdata/todoitem/edit/{todoItem.Id}";
    }

    private async void Back()
    {
        await JSRuntime.InvokeVoidAsync("window.history.back");
    }

}

 

实现编辑页面

主要是把TodoItem的各个属性,绑定到Razor组件。输入类型涵盖了文本,选择列表,开关。注意,checkbox如果想设置选中状态,必须在元素的属性中增加checked这个属性,它无法定义一个变量去绑定,Blazor提供了@attributes可以绑定动态属性,把它绑定到一个字典Dictionary<string, object>即可,正好解决需要单独出现的属性。这个方法也适用于input组件的disabled禁用。

 

@page "/fetchdata/todoitem/edit/{Id:int}"

@using MaBlaApp.Data
@inject TodoService MyTodoService
@inject IJSRuntime JSRuntime

<ul class="list-group">
    <li class="list-group-item list-group-item-primary d-flex justify-content-between">
        <strong class="align-self-center">修改任务</strong>
        <button class="btn btn-primary btn-sm" @onclick=Back>返回</button>
    </li>
</ul>

@if (todoItem is null)
{
    <p><em>任务不存在...</em></p>
}
else
{
    <ul class="list-group" style="overflow:auto">
        <li class="list-group-item d-flex justify-content-between mb-1">
            <strong class="align-self-center">@nameof(todoItem.Id)</strong>
            <small>@todoItem.Id</small>
        </li>
        <li class="list-group-item d-flex justify-content-between mb-1">
            <strong class="align-self-center">@nameof(todoItem.Title)</strong>
            <input type="text" class="form-control" style="width: 50%;" maxlength="20"
            @bind-value="todoItem.Title" placeholder="任务标题" />
        </li>
        <li class="list-group-item d-flex justify-content-between mb-1">
            <strong class="align-self-center">@nameof(todoItem.Description)</strong>
            <input type="text" class="form-control" style="width: 50%;" maxlength="20"
            @bind-value="todoItem.Description" placeholder="任务描述" />
        </li>
        <li class="list-group-item d-flex justify-content-between mb-1">
            <strong class="align-self-center">@nameof(todoItem.CreatedDate)</strong>
            <input type="date" class="form-control" style="width: 50%;"
            @bind-value="todoItem.CreatedDate" min="2023-1-1" max="2023-12-31" />
        </li>
        <li class="list-group-item d-flex justify-content-between mb-1">
            <strong class="align-self-center">优先级</strong>
            <select class="form-control" style="width: 50%;"
                    @bind="todoItem.Priority">
                <option value=@TodoPriority.Low>低</option>
                <option value=@TodoPriority.Middle>中</option>
                <option value=@TodoPriority.High>高</option>
            </select>
        </li>
        <li class="list-group-item d-flex justify-content-between mb-1">
            <strong class="align-self-center">@nameof(todoItem.IsFinished)</strong>
            <div class="form-check form-switch">
                <input type="checkbox" class="form-check-input" @attributes=IsFinishedCss
                @bind-value="todoItem.IsFinished" />
            </div>
        </li>
    </ul>
}

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

    private TodoItem todoItem;

    private Dictionary<string, object>? IsFinishedCss => todoItem.IsFinished ? new() { { "checked", "" }, } : null;

    protected override void OnInitialized()
    {
        todoItem = MyTodoService.TodoItems.FirstOrDefault(x => x.Id == Id);

        if (todoItem is null)
            return;

    }

    private async void Back()
    {
        await JSRuntime.InvokeVoidAsync("window.history.back");
    }
}

 

新建任务页面也差不多,详见项目仓库的代码。

 

测试效果

在手机模拟器上跑了一下,功能是对的,虽然不好看,就这样吧。

 

 

 

DEMO代码地址:https://gitee.com/woodsun/mauiblazorapp

 

posted on 2023-01-02 15:15  SunnyTrudeau  阅读(704)  评论(0编辑  收藏  举报