使用 C# 方法在 Blazor 中创建弹出窗口
Creating a popup in Blazor using C# method
我有一个带有按钮的简单页面 index.razor
:
<a class="btn btn-login" @onclick="RedirectPage" >Log in</a>
<div
@bind-Visible="@InvalidLogin"
BodyText="Error">
</div>
@code{
InvalidLogin {get; set;} = false;
}
其中函数 RedirectPage
检查值是否有效。如果不是,我想要一个提供信息的弹出窗口:
private void RedirectPage
{
this.InvalidLogin = true;
}
此函数在 index.razor.cs
中,并已在正确的命名空间中添加 @using
。
如何创建它以便在单击按钮时显示弹出窗口?
您可以创建一个简单的弹出(或模态对话框)组件。下面,我使用 Bootstrap 5 toast 组件编写了一个示例弹出式剃须刀组件。
Popup.razor
文件
@{
var showClass = IsVisible ? "d-block" : "d-none";
}
<div class="toast-container p-3 @showClass" data-bs-autohide="true" data-bs-delay="5000">
<div class="toast show" role="alert" aria-live="assertive" aria-atomic="true">
<div class="toast-header">
<strong class="me-auto">@HeaderText</strong>
<button type="button" class="btn-close" aria-label="Close" @onclick="Close"></button>
</div>
<div class="toast-body">
@BodyText
</div>
</div>
</div>
@code {
[Parameter]
public bool IsVisible { get; set; }
[Parameter]
public EventCallback<bool> IsVisibleChanged { get; set; }
[Parameter]
public string? HeaderText { get; set; }
[Parameter]
public string? BodyText { get; set; }
public void Show(string bodyText, string headerText = "")
{
HeaderText = headerText;
BodyText = bodyText;
IsVisible = true;
StateHasChanged();
}
private void Close()
{
HeaderText = string.Empty;
BodyText = string.Empty;
IsVisible = false;
StateHasChanged();
}
}
在您的代码中使用 Popup
razor 组件:
<a class="btn btn-login" @onclick="RedirectPage" >Log in</a>
<Popup @ref="popupRef" />
@code{
private Popup popupRef;
private void RedirectPage()
{
// Shows the popup at the center of the screen
popupRef.Show("Popup body text");
}
}
如何在不依赖第三方库的情况下创建对话框。
我不得不使用最少量的 js,因为新的 HTML5 <dialog...
元素只能用它在对话框模式下打开 .showModal()
而不是通过操作属性来打开。
wwwroot/scripts/dialogJsInteropt.js
export function showDialog(element, parm) {
return element.showModal();
}
export function closeDialog(element, parm) {
return element.close();
}
Dialog.razor
<CascadingValue Value=@this IsFixed=true >
<dialog @ref="@dialogElement" @attributes=@CapturedAttributes>
@if(visible)
{
@ChildContent
}
</dialog>
</CascadingValue>
Dialog.razor.cs
public partial class Dialog : ComponentBase, IAsyncDisposable
{
private readonly Lazy<Task<IJSObjectReference>> moduleTask;
private ElementReference dialogElement;
private bool visible = false;
public Dialog()
{
moduleTask = new(() => jsRuntime.InvokeAsync<IJSObjectReference>(
identifier: "import",
args: "./scripts/dialogJsInterop.js")
.AsTask());
}
[Inject]
private IJSRuntime jsRuntime { get; set; }
[Parameter]
public RenderFragment ChildContent { get; set; }
[Parameter(CaptureUnmatchedValues = true)]
public Dictionary<string, object> CapturedAttributes { get; set; }
public async ValueTask ShowDialogAsync()
{
var module = await moduleTask.Value;
await module.InvokeVoidAsync("showDialog", dialogElement);
visible = true;
}
public async ValueTask CloseDialogAsync()
{
var module = await moduleTask.Value;
await module.InvokeVoidAsync("closeDialog", dialogElement);
visible = false;
}
public async ValueTask DisposeAsync()
{
if (moduleTask.IsValueCreated)
{
var module = await moduleTask.Value;
await module.DisposeAsync();
}
}
}
在这个阶段你有一个有效的对话。
为了更方便,我添加了以下组件。
注意:我从这里开始使用 bootstrap 进行样式设置,例如可以轻松将其更改为 tailwind。
DialogCloseButton.razor
<button @attributes=CapturedAttributes @onclick=@CloseDialog />
DialogCloseButton.razor.cs
public partial class DialogCloseButton : ComponentBase
{
[CascadingParameter]
public Dialog Dialog { get; set; }
[Parameter(CaptureUnmatchedValues = true)]
public Dictionary<string, object> CapturedAttributes { get; set; } = new Dictionary<string, object>
{
{ "class", "btn btn-close" }
};
private async Task CloseDialog() => await Dialog.CloseDialogAsync();
}
DialogCloseButton.razor.css
.btn:focus {
box-shadow: none;
}
DialogLayout.razor
<div class="d-flex flex-row justify-content-between border-bottom border-1">
<div class="flex-fill p-1 ps-3 fw-bolder user-select-none app-gradient text-white">
@Header
</div>
<div class="p-1">
<DialogCloseButton />
</div>
</div>
<div class="p-3">
@Content
</div>
DialogLayout.razor.cs
public partial class DialogLayout
{
[Parameter]
public RenderFragment Header { get; set; }
[Parameter]
public RenderFragment Content { get; set; }
}
Usage :
<Dialog @ref=@dialog class="p-0 border rounded shadow">
<DialogLayout>
<Header>
<MessagesIcon Size=16 /> Add Message
</Header>
<Content>
<MessageFormView />
</Content>
</DialogLayout>
</Dialog>
<button class="btn btn-outline-success" @onclick=@OpenDialog>Add Message</button>
@code {
private Dialog dialog;
...
private async Task OpenDialog() => await dialog.ShowDialogAsync();
}
这是您所问内容的一个非常简单的示例(我将所有内容都放在 index.razor
文件中,但是您可以使用 CSS 隔离和专用的 .cs
文件来处理所有@code{}
部分的内容。
@page "/index"
<style>
.active {
display: block;
}
.inactive {
display: none;
}
</style>
<a class="btn btn-login" @onclick="RedirectPage" >Log in</a>
<div class="@PopupClass">
Error: @ErrorText
</div>
@code{
bool InvalidLogin {get; set;} = false;
string PopupClass => InvalidLogin ? "active" : "inactive";
public string ErrorText { get; set; } = "Example of exception";
private void RedirectPage()
{
this.InvalidLogin = !this.InvalidLogin;
}
}
当然,您需要自己适应这个示例以实现更具体的业务逻辑。
我有一个带有按钮的简单页面 index.razor
:
<a class="btn btn-login" @onclick="RedirectPage" >Log in</a>
<div
@bind-Visible="@InvalidLogin"
BodyText="Error">
</div>
@code{
InvalidLogin {get; set;} = false;
}
其中函数 RedirectPage
检查值是否有效。如果不是,我想要一个提供信息的弹出窗口:
private void RedirectPage
{
this.InvalidLogin = true;
}
此函数在 index.razor.cs
中,并已在正确的命名空间中添加 @using
。
如何创建它以便在单击按钮时显示弹出窗口?
您可以创建一个简单的弹出(或模态对话框)组件。下面,我使用 Bootstrap 5 toast 组件编写了一个示例弹出式剃须刀组件。
Popup.razor
文件
@{
var showClass = IsVisible ? "d-block" : "d-none";
}
<div class="toast-container p-3 @showClass" data-bs-autohide="true" data-bs-delay="5000">
<div class="toast show" role="alert" aria-live="assertive" aria-atomic="true">
<div class="toast-header">
<strong class="me-auto">@HeaderText</strong>
<button type="button" class="btn-close" aria-label="Close" @onclick="Close"></button>
</div>
<div class="toast-body">
@BodyText
</div>
</div>
</div>
@code {
[Parameter]
public bool IsVisible { get; set; }
[Parameter]
public EventCallback<bool> IsVisibleChanged { get; set; }
[Parameter]
public string? HeaderText { get; set; }
[Parameter]
public string? BodyText { get; set; }
public void Show(string bodyText, string headerText = "")
{
HeaderText = headerText;
BodyText = bodyText;
IsVisible = true;
StateHasChanged();
}
private void Close()
{
HeaderText = string.Empty;
BodyText = string.Empty;
IsVisible = false;
StateHasChanged();
}
}
在您的代码中使用 Popup
razor 组件:
<a class="btn btn-login" @onclick="RedirectPage" >Log in</a>
<Popup @ref="popupRef" />
@code{
private Popup popupRef;
private void RedirectPage()
{
// Shows the popup at the center of the screen
popupRef.Show("Popup body text");
}
}
如何在不依赖第三方库的情况下创建对话框。
我不得不使用最少量的 js,因为新的 HTML5 <dialog...
元素只能用它在对话框模式下打开 .showModal()
而不是通过操作属性来打开。
wwwroot/scripts/dialogJsInteropt.js
export function showDialog(element, parm) {
return element.showModal();
}
export function closeDialog(element, parm) {
return element.close();
}
Dialog.razor
<CascadingValue Value=@this IsFixed=true >
<dialog @ref="@dialogElement" @attributes=@CapturedAttributes>
@if(visible)
{
@ChildContent
}
</dialog>
</CascadingValue>
Dialog.razor.cs
public partial class Dialog : ComponentBase, IAsyncDisposable
{
private readonly Lazy<Task<IJSObjectReference>> moduleTask;
private ElementReference dialogElement;
private bool visible = false;
public Dialog()
{
moduleTask = new(() => jsRuntime.InvokeAsync<IJSObjectReference>(
identifier: "import",
args: "./scripts/dialogJsInterop.js")
.AsTask());
}
[Inject]
private IJSRuntime jsRuntime { get; set; }
[Parameter]
public RenderFragment ChildContent { get; set; }
[Parameter(CaptureUnmatchedValues = true)]
public Dictionary<string, object> CapturedAttributes { get; set; }
public async ValueTask ShowDialogAsync()
{
var module = await moduleTask.Value;
await module.InvokeVoidAsync("showDialog", dialogElement);
visible = true;
}
public async ValueTask CloseDialogAsync()
{
var module = await moduleTask.Value;
await module.InvokeVoidAsync("closeDialog", dialogElement);
visible = false;
}
public async ValueTask DisposeAsync()
{
if (moduleTask.IsValueCreated)
{
var module = await moduleTask.Value;
await module.DisposeAsync();
}
}
}
在这个阶段你有一个有效的对话。
为了更方便,我添加了以下组件。 注意:我从这里开始使用 bootstrap 进行样式设置,例如可以轻松将其更改为 tailwind。
DialogCloseButton.razor
<button @attributes=CapturedAttributes @onclick=@CloseDialog />
DialogCloseButton.razor.cs
public partial class DialogCloseButton : ComponentBase
{
[CascadingParameter]
public Dialog Dialog { get; set; }
[Parameter(CaptureUnmatchedValues = true)]
public Dictionary<string, object> CapturedAttributes { get; set; } = new Dictionary<string, object>
{
{ "class", "btn btn-close" }
};
private async Task CloseDialog() => await Dialog.CloseDialogAsync();
}
DialogCloseButton.razor.css
.btn:focus {
box-shadow: none;
}
DialogLayout.razor
<div class="d-flex flex-row justify-content-between border-bottom border-1">
<div class="flex-fill p-1 ps-3 fw-bolder user-select-none app-gradient text-white">
@Header
</div>
<div class="p-1">
<DialogCloseButton />
</div>
</div>
<div class="p-3">
@Content
</div>
DialogLayout.razor.cs
public partial class DialogLayout
{
[Parameter]
public RenderFragment Header { get; set; }
[Parameter]
public RenderFragment Content { get; set; }
}
Usage :
<Dialog @ref=@dialog class="p-0 border rounded shadow">
<DialogLayout>
<Header>
<MessagesIcon Size=16 /> Add Message
</Header>
<Content>
<MessageFormView />
</Content>
</DialogLayout>
</Dialog>
<button class="btn btn-outline-success" @onclick=@OpenDialog>Add Message</button>
@code {
private Dialog dialog;
...
private async Task OpenDialog() => await dialog.ShowDialogAsync();
}
这是您所问内容的一个非常简单的示例(我将所有内容都放在 index.razor
文件中,但是您可以使用 CSS 隔离和专用的 .cs
文件来处理所有@code{}
部分的内容。
@page "/index"
<style>
.active {
display: block;
}
.inactive {
display: none;
}
</style>
<a class="btn btn-login" @onclick="RedirectPage" >Log in</a>
<div class="@PopupClass">
Error: @ErrorText
</div>
@code{
bool InvalidLogin {get; set;} = false;
string PopupClass => InvalidLogin ? "active" : "inactive";
public string ErrorText { get; set; } = "Example of exception";
private void RedirectPage()
{
this.InvalidLogin = !this.InvalidLogin;
}
}
当然,您需要自己适应这个示例以实现更具体的业务逻辑。