使用 C# 方法在 Blazor 中创建弹出窗口

B.Q*_*ink 6 c# razor blazor

我有一个index.razor带有按钮的简单页面:

<a class="btn btn-login" @onclick="RedirectPage" >Log in</a>

<div
    @bind-Visible="@InvalidLogin"
    BodyText="Error">
</div>

@code{
    InvalidLogin {get; set;} = false;
}
Run Code Online (Sandbox Code Playgroud)

该函数RedirectPage检查值是否有效。如果不是,我想要一个弹出窗口提供信息:

private void RedirectPage
{
    this.InvalidLogin = true;
}
Run Code Online (Sandbox Code Playgroud)

该函数位于 中index.razor.cs,并且已添加到@using正确的命名空间中。

如何创建它以便在单击按钮时显示弹出窗口?

小智 14

您可以创建一个简单的弹出(或模式对话框)组件。下面,我使用 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();
    }
}
Run Code Online (Sandbox Code Playgroud)

Popup在代码中使用剃刀组件:

<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");
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 谢谢,经过一些改变,我让它工作了。 (2认同)

Bri*_*ker 6

如何在不依赖第三方库的情况下创建对话框。

我必须使用最少量的 js,因为新的 HTML5<dialog...元素只能在对话框模式下打开,而.showModal()不能通过操作属性来打开。

wwwroot/scripts/dialogJsInterop.js

export function showDialog(element, parm) {
    return element.showModal();
}

export function closeDialog(element, parm) {
    return element.close();
}
Run Code Online (Sandbox Code Playgroud)

Dialog.razor

<CascadingValue Value=@this IsFixed=true >
    <dialog @ref="@dialogElement" @attributes=@CapturedAttributes>
    @if(visible)
    {
        @ChildContent
    }
    </dialog>
</CascadingValue>
Run Code Online (Sandbox Code Playgroud)

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();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

在这个阶段,您将看到一个可以运行的对话框。

我添加了以下组件以使其更加方便。注意:我确实使用从这里开始的引导程序来进行样式设置,例如可以轻松地将其更改为顺风。

DialogCloseButton.razor

<button @attributes=CapturedAttributes @onclick=@CloseDialog />
Run Code Online (Sandbox Code Playgroud)

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();
}
Run Code Online (Sandbox Code Playgroud)

DialogCloseButton.razor.css

.btn:focus {
    box-shadow: none;
}
Run Code Online (Sandbox Code Playgroud)

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>

Run Code Online (Sandbox Code Playgroud)

DialogLayout.razor.cs

public partial class DialogLayout
{
    [Parameter]
    public RenderFragment Header { get; set; }

    [Parameter]
    public RenderFragment Content { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

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();
}
Run Code Online (Sandbox Code Playgroud)