【问题标题】:blazor add parameters to templated componentblazor 向模板化组件添加参数
【发布时间】:2022-02-01 09:55:15
【问题描述】:

我有一个 Blazor 弹出窗口,它需要一个模板来显示他的内容:

CustomPopup.razor

<Popup
    @bind-Visible="@CreatePopupVisible"
    HorizontalAlignment="HorizontalAlignment.Center"
    VerticalAlignment="VerticalAlignment.Center"
    ShowFooter="true"
    HeaderText="@("Create" + Label)">
    <BodyTemplate>
        @EditForm
    </BodyTemplate>
    <FooterContentTemplate>
    </FooterContentTemplate>
</Popup>

@code {
    [Parameter]
    public string? Label { get; set; }

    [Parameter]
    public RenderFragment EditForm { get; set; }

    bool CreatePopupVisible { get; set; }

}

我向这个组件传递了一个带有 2 个按钮的 EditForm,该按钮采用一个函数来处理取消选项:

CustomEditForm.razor

<EditForm Model="Entity" OnValidSubmit="@HandleValidSubmit">
    <DataAnnotationsValidator />
    <ValidationSummary />
    <div class="d-flex flex-column">
        <InputNumber id="factory-id" class="mt-2 mb-2" @bind-Value="Entity.Id" />
        <InputText id="factory-businessname" class="mt-2 mb-2" @bind-Value="Entity.BusinessName" />
        <InputText id="factory-address" class="mt-2 mb-2" @bind-Value="Entity.Address" />
        <div class="d-flex flex-row">
            <button class="btn btn-primary mt-2 mb-2 flex-grow-1" type="submit">Modifica</button>
            <button @onclick="HandleCancel" class="btn btn-secondary mt-2 mb-2 flex-grow-1" type="submit">Annulla</button>
        </div>
    </div>
</EditForm>

@code {

    [Parameter]
    public Action HandleCancel { get; set; }
    

    [Parameter]
    public Factory Entity { get; set; }
    
    private void HandleValidSubmit()
    {
        Logger.LogInformation("HandleValidSubmit called");
    }
}

如果我像这样正常使用 EditForm:

SomeFile.razor

<CustomEditForm HandleCancel="()=>{}">

一切都很好,但是当我在模板化组件中使用它时,如何从 CustomPupup.razor 文件中将函数传递给他?

当有人点击取消按钮时,我需要传递一个函数将 CreatePopupVisible 设置为 false

提前寻求帮助!

编辑

寻求帮助,但我认为我提供的信息不足,无法得到正确答案,我的错

所以,我希望能够正常调用 CustomEditForm 并传递由父级定义的函数来管理 HandleCancel,如下所示:

MainPage.razor

@page ...

<Grid @ref="Grid">
//the grid has a method that closes this CustomEditForm
    <Template>
        <CustomEditForm HandleCancel="() => Grid.CancelRowEdit()"/>
    </Template>
</Grid>

但我也想使用自己内部定义的函数来关闭弹出窗口,如下所示:

另一个页面.razor

<CustomPopup>
    <EditForm>
        <CustomEditForm Entity="new Factory()"/>
    </EditForm>
</CustomPopup>

在这种情况下,编辑表单应该通过调用 CustomPopup 定义的方法来处理取消

【问题讨论】:

    标签: blazor blazor-webassembly asp.net-blazor


    【解决方案1】:

    听起来您只是想将内部方法的引用传递给RenderFragment,您可以使用RenderFragment&lt;Action&gt; 执行此操作 - 因为HandleCancel 期望Action 它可以invoke:

    <Popup
        @bind-Visible="@CreatePopupVisible"
        HorizontalAlignment="HorizontalAlignment.Center"
        VerticalAlignment="VerticalAlignment.Center"
        ShowFooter="true"
        HeaderText="@("Create" + Label)">
        <BodyTemplate>
            @EditForm(ClosePopup)
        </BodyTemplate>
        <FooterContentTemplate>
        </FooterContentTemplate>
    </Popup>
    
    @code {
        [Parameter]
        public string? Label { get; set; }
    
        [Parameter]
        public RenderFragment<Action> EditForm { get; set; }
    
        bool CreatePopupVisible { get; set; }
    
        void ClosePopup() 
        {
            CreatePopupVisible = false;
    
            // Because this method will be called by some external code
            // You should tell this component to render:
    
            InvokeAsync(StateHasChanged);
        } 
    }
    

    要使用它,标记可以引用EditForm RenderFragment 的context,即Action

    <CustomPopup>
        <EditForm>
            <CustomEditForm Entity="new Factory()" HandleCancel=@context/>
        </EditForm>
    </CustomPopup>
    

    Try it out

    【讨论】:

    • 这太完美了!
    【解决方案2】:

    由于您的问题中没有足够的代码作为答案的基础,因此我将使用一个非常简单的组件来演示如何做您想做的事情。

    这是我的“PopUp”模拟器。

    @if (this.Visible)
    {
        <h3>PopUp</h3>
        @this.ChildContent
    }
    
    @code {
        [Parameter] public RenderFragment? ChildContent { get; set; }
        [Parameter] public bool Visible { get; set; }
    }
    

    然后是我的 CustomPopUp。请注意,我正在使用 this 并有一个公共的 Close 方法。

    
    <PopUp Visible="this.CreatePopupVisible">
        <CascadingValue Value=this>
        @this.ChildContent
        </CascadingValue>
    </PopUp>
    
    @code {
        [Parameter] public RenderFragment? ChildContent { get; set; }
    
        bool CreatePopupVisible { get; set; }
    
        public void Show()
        {
            this.CreatePopupVisible = true;
        }
    
        public void Close()
        {
            this.CreatePopupVisible = false;
            this.StateHasChanged();
        }
    }
    

    接下来是我的 EditForm。请注意,我捕获了 CustomMyPopUp 的 Cascaded 实例。 My Cancel 现在检查我们是否有级联值(我们在 PopUp 上下文中),如果有,则在弹出窗口上调用 Close。它还检查HandleCancel 上是否有注册的委托,并且只有在有时才调用它。

    <div class="m-2 p-5 bg-light">
    <h3>EditForm</h3>
    <div class="p-2 m-2">
    <button class="btn btn-danger" @onclick="this.Cancel">Cancel</button>
    </div>
    </div>
    @code {
        [CascadingParameter] private CustomPopUp? myPopUp { get; set; }
        [Parameter] public EventCallback<bool> HandleCancel { get; set; }
    
        public async Task Cancel()
        {
            if (this.myPopUp is not null)
                myPopUp.Close();
            if (this.HandleCancel.HasDelegate)
                await HandleCancel.InvokeAsync();
        }
    }
    

    终于要测试我的页面了:

    @page "/PopUp"
    <h3>CascadePage</h3>
    <CustomPopUp @ref=this.myPopUp>
        <MyEditForm />
    </CustomPopUp>
    
    <div class="p-2 m-2">
    <button class="btn btn-primary" @onclick="this.Show">Show</button>
    </div>
    
    @code {
        private CustomPopUp? myPopUp;
    
        public void Show()
        => this.myPopUp?.Show();
    }
    

    【讨论】:

    • 我正在更新问题以获得更多详细信息,请帮忙
    • 所以,如果我没看错,您希望能够通过 Cancel 按钮从 EditForm 内部以及在父 Grid 表单中关闭包含编辑器的弹出框从行中单击某种类型的CancelEdit 控件?
    • CustomEditForm 有一个标记为关闭的按钮,按下时它会调用作为属性传递的函数,CustomEditForm 可以单独放置在网格旁边,因此当单击编辑表单上的关闭时网格做了一些事情,但它也需要能够作为 RenderFragment 传递给 CustomPopup,问题是关闭 CustomPopup 的方法是在附加了 Renderfragment 的 CustomPopup 中声明的,所以我不能将参数传递给它跨度>
    • 基本上我希望能够将函数直接传递给组件和作为渲染片段给出的组件,唯一的问题是关闭弹出窗口的代码与附加文件在同一个文件中的渲染片段所以我不能使用常规的标记我用@EditForm附加它但现在我不能传递参数
    • [礼貌] 我认为你需要重新考虑你的设计。为了实现您的设想,我认为您需要组件、表单和页面通过其进行通信的服务。您还需要停止将表单传递为RenderFragment,而将传递视为Type。但是从根本上讲,我认为您使设计过于复杂。您不能使用普通的模态对话框,例如 BLAZORED - github.com/Blazored/Modal 或更简单的我在这里写的 codeproject.com/Articles/5286721/…
    猜你喜欢
    • 2020-08-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多