學習ASP.NET Core Blazor程式設計系列二十一——資料重新整理

2023-01-15 21:00:42
學習ASP.NET Core Blazor程式設計系列一——綜述
學習ASP.NET Core Blazor程式設計系列八——資料校驗
學習ASP.NET Core Blazor程式設計系列十三——路由(完)
學習ASP.NET Core Blazor程式設計系列十五——查詢
 學習ASP.NET Core Blazor程式設計系列十七——檔案上傳(上)     
學習ASP.NET Core Blazor程式設計系列二十——檔案上傳(完)
 

           在上一篇 學習ASP.NET Core Blazor程式設計系列二十——檔案上傳(完) 文章中曾經談過檔案上傳功能遺留了二個問題。第一個問題我們已經在上一篇文章中解決了,第二個問題,就是資料重新整理問題,這不僅僅是上傳中會碰到,只要是用資料列表或表格呈現資料,都可能會碰到沒有及時重新整理,資料不是最新的這個問題。

十、重新整理資料

Blazor 繫結(繫結就是重新整理)機制有以下幾種

  1. 首次載入時的自動繫結
  2. 呼叫 StateHasChanged 強制重新系結(重新系結即重新整理)
  3. 註冊事件自動重新整理

Blazor元件在第一次渲染完成之後,ShouldRender 會返回為 false,然後後面呼叫都返回 false,對於任意一個元件,若出現沒重新整理的情況下,請考慮這個因素。
那麼,如何讓Blazor元件進行重新整理呢?方法很簡單,手動呼叫該元件的StateHasChanged 方法,然後繫結資料。

StateHasChanged 方法

        這個方法至關重要,我們來看看這個方法裡面有什麼。如下圖。

    

      資料重新整理的流程以上圖來講解,接下來,我們以具體的程式碼來實現此功能。

1. 在Visual Studio 2022中的解決方案資源管理器中使用滑鼠左鍵雙擊開啟UpFileInfoList.razor檔案。在@code程式碼塊中宣告一個事件。程式碼如下:

 [Parameter]
    public EventCallback RefterData { get; set; }

2.在Visual Studio 2022中的解決方案資源管理器中使用滑鼠左鍵雙擊開啟FileUpload1.razor檔案。在@code程式碼塊中用程式碼實現RefterData事件的一個方法 RefterDataHandler,並在UpFileInfoList元件中呼叫我們剛才寫的RefterDataHandler方法,在上傳方法中呼叫RefterDtaHandler方法 。程式碼如下:

@page "/FileUpload1"
@using BlazorAppDemo.Models
@using BlazorAppDemo.Utils

@using Microsoft.AspNetCore.Mvc.ModelBinding
@using Microsoft.EntityFrameworkCore
@inject IWebHostEnvironment Environ
@inject IDbContextFactory<BookContext> dbFactory
 
<h3>多檔案上傳範例</h3>
<p>
    <label>
        提示資訊:@Message
 
    </label>
</p>
<p>
    <label>
        上傳檔案最大可以為:<input type="number" @bind="maxFileSize"/>位元組
 
    </label>
</p>
<p>
    <label>
        一次可上傳:<input type="number" @bind="maxAllowedFiles" />個檔案
 
    </label>
</p>
<p>
    <label>
        選擇上傳檔案:<InputFile OnChange="@LoadFiles" multiple />
 
    </label>
    <BlazorAppDemo.Pages.Descri.UpFileInfoList RefterData="RefterDataHandler" @ref="@upfileList"></BlazorAppDemo.Pages.Descri.UpFileInfoList>

</p>
@if (isLoading)
{
    <p>檔案上傳中......</p>
}
else
{
    <ul>
        @foreach (var file in loadedFiles)
        {
            <li>
                <ul>
                    <li>檔名:@file.Name</li>
                    <li>最後修改時間:@file.LastModified.ToString()</li>
                    <li>檔案大小(byte):@file.Size</li>
                    <li>檔案型別:@file.ContentType</li>
                </ul>
            </li>
           
        }
 
    </ul>
}
 
@code {

    private List<IBrowserFile> loadedFiles = new();
    private long maxFileSize = 1024 * 18;

    private int maxAllowedFiles = 2;
    private bool isLoading;

    private string Message = string.Empty;
    private BlazorAppDemo.Pages.Descri.UpFileInfoList upfileList;

    private async Task LoadFiles(InputFileChangeEventArgs e)
    {

        isLoading = true;
        loadedFiles.Clear();
        foreach (var file in e.GetMultipleFiles(maxAllowedFiles))

        {
            try
            {

                ModelStateDictionary modelState = new ModelStateDictionary();
                loadedFiles.Add(file);

                FileHelpers.db = dbFactory.CreateDbContext();
                string result=  await FileHelpers.ProcessFormFile(file, modelState, Environ, maxFileSize);
                if (string.IsNullOrEmpty(result))
                {
                    Message = "上傳成功!";
                    RefterDataHandler();
 
                }else
                    Message = "上傳失敗!";
            }
            catch (Exception ex)
            {
                Message = ex.Message;
 
            }

        }
        isLoading = false;
    }

    public void RefterDataHandler()
    {
        StateHasChanged();
        upfileList.BindData();
    }


}

 

3.我們在Visual Studio 2022中切換到UpFileInfoList.razor頁面,並在ShowConfirmMsg方法中呼叫RefterData方法 。具體程式碼如下。
@page "/Descri/UpFileInfoList"
@using BlazorAppDemo.Models

@using BlazorAppDemo.Utils
@using Microsoft.EntityFrameworkCore
 
@inject IDbContextFactory<BookContext> dbFactory
@inject IJSRuntime JsRuntime

 
<h3>已上傳檔案列表</h3>
<table class="table" width="99%">

    <thead>

      
        <tr>
            <th></th>
            <th>
                @HtmlHelper.GetDisplayName(fileDesc,m=>m.Name)
 
            </th>
            <th>
                @HtmlHelper.GetDisplayName(fileDesc ,m=> m.NewName)
            </th>
 
            <th class="text-center">
                @HtmlHelper.GetDisplayName(fileDesc ,m=>m.UploadDateTime)
            </th>
            <th class="text-center">
                @HtmlHelper.GetDisplayName(fileDesc ,m=> m.FileSize)
            </th>
        </tr>
    </thead>
    <tbody>
        @foreach (var item in fileDescs)
        {
            <tr>
                <td>

                    <button id="delete" class="btn btn-primary"  @onclick="@(async e => await ShowConfirmMsg(e, @item.ID))">刪除</button>
                </td>
                <td>
                    @item.Name
 
                </td>
                <td>
                    @item.NewName
 
                </td>
                <td class="text-center">
                    @item.UploadDateTime
                </td>
                <td class="text-center">
                    @item.FileSize
                </td>
            </tr>
        }
    </tbody>
</table>
 
@code {
    private static BookContext _context;


    private List<FileDescribe> fileDescs = new List<FileDescribe>();
    private FileDescribe fileDesc = new FileDescribe();
    [Parameter]
    public EventCallback RefterData { get; set; }
    protected override async Task OnInitializedAsync()
    {
 
        BindData();
        await base.OnInitializedAsync();
    }
 
    public void BindData()
    {
        _context = dbFactory.CreateDbContext();
        fileDescs = _context.FileDescribe.ToList();
 
    }


    public void DeleteFile(MouseEventArgs e, int Id)
    {
        List<int> listId = new();
        listId.Add(Id);

        int[] Ids= listId.ToArray();
        var entity = _context.Find<FileDescribe>(Id);

        _context.Remove<FileDescribe>(entity);
        _context.SaveChangesAsync();
    
    }

    public async Task ShowConfirmMsg(MouseEventArgs e,int Id)
    {

        if (await JsRuntime.InvokeAsync<bool>("confirm",$"你是否確認要刪除當前檔案?"))
        {
            DeleteFile(e, Id);
         
            await RefterData.InvokeAsync();
        }
    }
 
}
4.在Visual Studio 2022中按F5執行圖書租賃管理應用程式,然後在瀏覽器中點選「上傳檔案」選單。如下圖。

 

5. 在瀏覽器的「多檔案上傳範例」頁面中使用滑鼠左鍵點選「選擇檔案」按鈕,在彈出的對話方塊中,選擇「1K檔案」,檔案將被上傳,檔案資訊會在上傳成功之後,及時更新到「已上傳檔案列表」中。如下圖。

 

 

   6.  在已上傳檔案列表中,點選要刪除的上傳檔案記錄前面的刪除按鈕。系統會彈出一個「你是否確認要刪除當前檔案」的提示資訊,如下圖。

 

 

7. 使用滑鼠左鍵點選「確定」按鈕,系統將把檔案資訊刪除,同時重新整理「已上傳檔案列表」資訊。如下圖。