我有一個應用程式,它由一個帶有側邊欄和標題的簡單布局組成。標題有一個顯示一些自定義資訊的文本(例如,用戶名、日期或只是當前視圖的名稱)。
<Layout Sider="true">
<LayoutSider>
<LayoutSiderContent>
<NavMenu />
</LayoutSiderContent>
</LayoutSider>
<Layout>
<LayoutHeader Fixed="true">
<Header Title="@Title"></Header> <!-- CUSTOM HEADER COMPONENT -->
</LayoutHeader>
<LayoutContent>
<CascadingAuthenticationState>
<Router AppAssembly="@typeof(Program).Assembly" PreferExactMatches="@true"> <!-- VIEW ROUTER-->
<Found Context="routeData">
<AuthorizeRouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)">
<NotAuthorized>
You are not Authorized to Access this App. Please make sure, that you logged in with your company account.
</NotAuthorized>
</AuthorizeRouteView>
</Found>
<NotFound>
<LayoutView Layout="@typeof(MainLayout)">
<p>Sorry, there's nothing at this address.</p>
</LayoutView>
</NotFound>
</Router>
</CascadingAuthenticationState>
</LayoutContent>
</Layout>
</Layout>
@code
{
private string Title { get; set; }
}
注意:Header 是我寫的一個簡單的組件,它只是輸出一個帶有一點 CSS 的文本。我還使用 Blazorise,它將基本的 HTML 物件包裝到 Blazor 組件中。
我沒有將此代碼放入我的代碼MainLayout.razor中,因為我希望在找不到頁面或用戶無權訪問特定頁面時顯示側邊欄和標題。
我遇到的問題是,我無法找到一個干凈的解決方案來更新我的標題。目前我這樣做了,但對我來說,它看起來像一個非常“hacky”的解決方案,它不會在沒有呼叫StateHasChanged.
我創建了一個名為 的類ViewBase.cs,我的所有頁面都從該類繼承并將標題作為級聯引數。
<Layout Sider="true">
<CascadingValue Value="@Title">
<Layout>
<LayoutHeader Fixed="true">
...
</LayoutHeader>
<LayoutContent>
...
</LayoutContent>
</Layout>
</CascadingValue>
</Layout>
^App.cshtml用級聯值調整
@inherits LayoutComponentBase
<CascadingValue Value="@Title">
@Body
</CascadingValue>
@code
{
private string title;
[CascadingParameter]
public string Title
{
get => this.title;
set
{
this.title = value;
this.StateHasChanged();
}
}
}
^MainLayout.razor
public class ViewBase : ComponentBase
{
private string title;
[CascadingParameter]
public string Title
{
get => this.title;
set
{
this.title = value;
this.StateHasChanged();
}
}
}
^ViewBase.cs
這允許我在視圖中以編程方式設定標題,通過撰寫this.Title = "My custom Title!". 這實作了基本功能,但我還想直接在 Blazor 視圖中控制標題。因此,我創建了一個簡單的組件HeaderControl。
@inherits Project.Shared.BaseComponents.ViewBase
@code {
[Parameter]
public string PTitle
{
get => this.Title;
set => this.Title = value;
}
}
然后我可以在我的視圖中使用這個組件,如下所示:
@page "/"
@inherits Project.Shared.BaseComponents.ViewBase
<HeaderControl PTitle="Hello World!"/>
<Div Class="w-100 h-100 d-flex flex-column align-items-center justify-content-between">
<!-- Page Content -->
</Div>
正如我所說,這有點作業,但StateHasChanged有點麻煩,特別是如果您需要每秒更新幾次標題(這是一個要求)。我監督了某種機制嗎?我認為這會很好,如果這可以通過一個事件來處理,其中新值被傳遞到層次結構(View.razor-> MainLayout.razor-> App.cshtml),但我想不出一種方法來做到這一點。我能想到的另一個解決方案是,我的組件中有一個靜態 oldscool C# 事件Header,它被我的HeaderControl組件呼叫。
uj5u.com熱心網友回復:
您需要使用帶有通知事件的服務。這是一個非常簡單的實作來演示原理。
標頭服務
public class HeaderService
{
public string Header { get; set; } = "Starting Header";
public event EventHandler? HeaderChanged;
public void SetHeader(string header)
{
Header = header;
HeaderChanged?.Invoke(this, EventArgs.Empty);
}
public void NotifyHeaderChanged()
=> HeaderChanged?.Invoke(this, EventArgs.Empty);
}
注冊Program:
builder.Services.AddScoped<HeaderService>();
標題組件
@inject HeaderService headerService
@implements IDisposable
<h3>@this.headerService.Header</h3>
@code {
protected override void OnInitialized()
=> this.headerService.HeaderChanged = this.OnChange;
private void OnChange(object? sender, EventArgs e)
=> this.InvokeAsync(StateHasChanged);
public void Dispose()
=> this.headerService.HeaderChanged -= this.OnChange;
}
應用程式:
<MyHeader />
<Router AppAssembly="@typeof(App).Assembly">
<Found Context="routeData">
<RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
<FocusOnNavigate RouteData="@routeData" Selector="h1" />
</Found>
<NotFound>
<PageTitle>Not found</PageTitle>
<LayoutView Layout="@typeof(MainLayout)">
<p role="alert">Sorry, there's nothing at this address.</p>
</LayoutView>
</NotFound>
</Router>
演示頁面:
@page "/"
@inject HeaderService headerService
<PageTitle>Index</PageTitle>
<div class="p-3">
<button class="btn btn-primary" @onclick=UpdateHeader>Say Hello</button>
</div>
Welcome to your new app.
@code {
private void UpdateHeader()
=> this.headerService.SetHeader($"Clicked at {DateTime.Now.ToLongTimeString()}");
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/466782.html
