首页 > 解决方案 > Blazor 中的级联值和 EventCallback 与布局组件

问题描述

我想通过三个组件传递值和事件回调:首先我有 MainLayout,它是一个 LayoutComponent

@inherits LayoutComponentBase

<div class="cms-container">
    <div class="header">
        <div class="header-logo">
            CMS
        </div>
        <div class="header-settings">
            <div class="header-settings__alert">
                <i class="fa fa-bell"></i>
                <div class="header-settings__alert--no">
                    <div class="header-settings__alert--no__text">
                        2
                    </div>
                </div>
                <ul class="cms-dropdown">
                    <li class="cms-dropdown__alert">
                        <span class="cms-dropdown__alert--status"><i class="fa fa-info-circle font-danger"></i></span>
                        <span class="cms-dropdown__alert--left">Följ upp händelse</span><span class="cms-dropdown__alert--right">1 dgr</span>
                    </li>
                    <li class="cms-dropdown__alert">
                        <span class="cms-dropdown__alert--status"><i class="fa fa-info-circle font-success"></i></span>
                        <span class="cms-dropdown__alert--left">Tidrapport behöver lämnas in</span><span class="cms-dropdown__alert--right">3 dgr</span>
                    </li>
                </ul>
            </div>
            <div class="header-settings__org">
                <span class="header-settings__org--text">
                    Kanal10.se
                </span>

                <ul class="cms-dropdown">
                    <li class="cms-dropdown__normal">
                        <div class="cms-dropdown__normal--icon">
                            <i class="fa fa-tasks"></i>
                        </div>
                        <div class="cms-dropdown__normal--text">Uppgifter</div>

                    </li>
                    <li class="cms-dropdown__normal">
                        <div class="cms-dropdown__normal--icon">
                            <i class="fa fa-users"></i>
                        </div>
                        <div class="cms-dropdown__normal--text">Användare</div>
                    </li>
                </ul>
            </div>

            <div class="header-settings__account">
                <i class="fa fa-user"></i>
                <ul class="cms-dropdown">
                    <li class="cms-dropdown__normal">
                        <div class="cms-dropdown__normal--icon">
                            <i class="fa fa-user"></i>
                        </div>
                        <div class="cms-dropdown__normal--text">Min profil</div>
                    </li>
                    <li class="cms-dropdown__normal">
                        <div class="cms-dropdown__normal--icon">
                            <i class="fa fa-money-check"></i>
                        </div>
                        <div class="cms-dropdown__normal--text">Lönebesked</div>
                    </li>
                </ul>
            </div>
            <div class="header-settings__system">
                <div class="header-settings__system--icon">
                    <i class="fa fa-cog"></i>
                </div>
                <ul class="cms-dropdown">
                    <li class="cms-dropdown__normal">
                        <div class="cms-dropdown__normal--icon">
                            <i class="fa fa-bars"></i>
                        </div>
                        <div class="cms-dropdown__normal--text">Menyer</div>
                    </li>
                    <li class="cms-dropdown__normal">
                        <div class="cms-dropdown__normal--icon">
                            <i class="fa fa-users"></i>
                        </div>
                        <div class="cms-dropdown__normal--text">Användare</div>
                    </li>
                    <li class="cms-dropdown__normal">
                        <div class="cms-dropdown__normal--icon">
                            <i class="fa fa-shield-alt"></i>
                        </div>
                        <div class="cms-dropdown__normal--text">Behörighetsgrupper</div>
                    </li>

                </ul>
            </div>
        </div>
    </div>
    <div class="LeftNav">
        <NavMenu />
    </div>
    <TelerikRootComponent>
        <div class="cms-content">

            @Body

        </div>
    </TelerikRootComponent>
    <div class="footer">
        <div class="footer-body">
            <div class="footer-body__left">

            </div>
            <div class="footer-body__right">
                <CascadingValue Value="visible">
                    <SaveAndCancelBtns OnBtnAction="?" />
                </CascadingValue>
            </div>
        </div>
    </div>
</div>

<BlazoredToasts Position="Blazored.Toast.Configuration.ToastPosition.TopCenter"
                Timeout="3"
                IconType="IconType.FontAwesome"
                SuccessClass="success-toast-override"
                SuccessIcon="fa fa-thumbs-up" />



@code {
    private bool visible = false;
}

然后我有一个名为的子组件Buttons.razor

@if (visible == true)
{
    <div class="footer-body__right--item">
        <button class="btn btn-primary" @onclick="Save" type="submit">Save</button>
    </div>
    <div class="footer-body__right--item">
        <button class="btn btn-cancel" @onclick="Cancel">Cancel</button>
    </div>
}
       [Parameter] public EventCallback<string> OnBtnAction { get; set; }
        [Parameter] public bool visible { get; set; }

        private void Save()
        {
            OnBtnAction.InvokeAsync("Save");
        }

        private void Cancel()
        {
            OnBtnAction.InvokeAsync("Cancel");
        }
    }

然后我有一个名为的组件剃须刀页面pageDetail.razor

@page "/pages/detail/{Id}"
@page "/pages/detail"

<div class="wrapper">
    <div class="cms-content__title">
        <div class="cms-content__title-left">
            Page Detail
        </div>
    </div>
    <div class="cms-content__page">
        <div class="cms-content__page-all">
            @if (cmsPage == null)
            {
                <ErrorMessage Message="Loading..." />
            }
            else
            {
        <div class="col-6">
            <EditForm Model="cmsPage" OnValidSubmit="SavePage">
                <DataAnnotationsValidator />
                <ValidationSummary />

                <div class="form-group">
                    <label for="PageTitle">Page Title</label>
                    <InputText @bind-Value="@cmsPage.PageTitle" class="form-control" id="PageTitle"></InputText>
                </div>
                <div class="form-group">
                    <label for="PageTitle">Page Descr</label>
                    <InputTextArea @bind-Value="@cmsPage.PageDescr" class="form-control" id="PageTitle"></InputTextArea>
                </div>
                <div class="form-group">
                    <label for="PageTitle">Page Url</label>
                    <InputText @bind-Value="@cmsPage.UrlName" class="form-control" id="PageTitle"></InputText>
                </div>
                <div class="form-group">
                    <label for="PageTitle">Page Type</label><br />
                    <TelerikComboBox Data="@cmsPageTypes" TextField="PageType" Width="100%" ValueField="PageTypeId" @bind-Value="selectedValue">
                    </TelerikComboBox>
                    <ValidationMessage For="@(() => cmsPage.PageTypeId)" />
                </div>
                <div class="form-group">
                    <label for="PageTitle">Parent Page</label><br />
                    <TelerikTreeView Data="@cmsPages" OnItemClick="@OnItemClickHandler">
                        <TreeViewBindings>
                            <TreeViewBinding IdField="PageId" TextField="PageTitle" ParentIdField="ParentId" HasChildrenField="false"></TreeViewBinding>
                        </TreeViewBindings>
                    </TelerikTreeView>
                </div>

                <button class="btn btn-primary" type="submit">Save</button>
                <button class="btn btn-danger" @onclick="DeletePage">Delete</button>
                <button class="btn btn-info" @onclick="BackToList">Back To List</button>

            </EditForm>
        </div>
               
            }
        </div>
    </div>
</div>

@code{
    "not sure how to implement the event button action"
}

我想要的是:

  1. 在 PageDetail 上设置可见参数,如果为 true,则显示 Buttons.razor 中的按钮或隐藏它们
  2. 当单击buttons.razor 中的按钮时,为那里的EditForm 处理PageDetail.razor 上的事件

问题是如何处理作为 LayoutComponent 的组件。不确定它如何符合逻辑。

如您所见,我已经开始实施它,但不确定如何连接不同的部分。

感谢帮助!彼得

标签: c#razorblazor

解决方案


我建议您查看这篇文章:https ://chrissinty.com/3-ways-to-communicate-between-components-in-blazor/ ,但通过<CascadingParameter>在布局中使用,您是其中的一部分。

在您的情况下,我不热衷于使用布尔值visible作为级联参数,这有点简单。级联值也位于错误的位置,因为它需要包装@Body渲染和按钮。

我会创建一个状态类并将该类级联任何想要使用它的孩子,通过包装@Body<SaveAndCancelBtns ..>

<CascadingValue Value="buttonState" >
    <TelerikRootComponent>
        <div class="cms-content">

            @Body

        </div>
    </TelerikRootComponent>
    <div class="footer">
        <div class="footer-body">
            <div class="footer-body__left">

            </div>
            <div class="footer-body__right">
                <SaveAndCancelBtns />
            </div>
        </div>
    </div>
</CascadingValue>

您还需要在布局代码中添加一个值:

  ButtonStates buttonState = new ButtonStates();

ButtonStates 类应该提供您需要的值和事件,例如

public class ButtonStates 
{
    public bool Visible { get; private set; }

    // etc
}

我没有将所有代码放在这里,而是在 github 上为您创建了一个简单的示例 repo: https ://github.com/conficient/CascadingStateExample

请注意,我刚刚使用了一个简单的状态容器并event从中传递事件。EventCallback<T>专门用于连接 Razor 组件之间的事件。


推荐阅读