.NET MAUI Blazor:如何从Shell传递字符串到Blazor组件参数
问题描述
我正在开发.NET MAUI Blazor混合应用,现有MainPage.xaml中的Shell代码,以及用于展示任务的ListOfTask Blazor页面。当前在ListOfTask中通过await App.Current.MainPage.Navigation.PushAsync(new NewPage1("test"))跳转到NewPage1,希望将该"test"字符串传递到/task1 Blazor页面中由[Parameter]修饰的MyProperty参数中,请教实现方法。
相关代码
MainPage.xaml
<?xml version="1.0" encoding="utf-8" ?> <Shell xmlns="http://schemas.microsoft.com/dotnet/2021/maui" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:local="clr-namespace:MauiApp14" x:Class="MauiApp14.MainPage" xmlns:pages="clr-namespace:MauiApp14.Components.Pages" xmlns:pagese="clr-namespace:MauiApp14.Components.Pages.Survey" xmlns:in="clr-namespace:MauiApp14.Components.Layout" > <TabBar> <!--<ShellContent Title="Settings" Icon="settings.png" ContentTemplate="{DataTemplate pages:NewPage4}" />--> <ShellContent Title="Home" Icon="icons_task.png"> <ContentPage> <BlazorWebView x:Name="Survey" HostPage="wwwroot/index.html"> <BlazorWebView.RootComponents> <RootComponent Selector="#app" ComponentType="{x:Type pagese:ListOftask}" /> </BlazorWebView.RootComponents> </BlazorWebView> </ContentPage> </ShellContent> </TabBar> </Shell>
ListOfTask Blazor页面
@page "/tasklist" @using MauiApp14.Components.Layout @inject NavigationManager navigationManager <table class="table"> <thead> <tr> <th>ID</th> <th>Task Name</th> <th>Description</th> <th>Actions</th> </tr> </thead> <tbody> @foreach (var task in tasks) { <tr> <td>@task.Id</td> <td>@task.Name</td> <td>@task.Description</td> <td> <button class="btn btn-primary" @onclick="() => StartTask(task)">Start</button> </td> </tr> } </tbody> </table> @code { private List<TaskModel> tasks; protected override void OnInitialized() { // Initialize the list of tasks tasks = new List<TaskModel> { new TaskModel { Id = 1, Name = "Task 1", Description = "Description for Task 1", RedirectUrl = "/task1" }, new TaskModel { Id = 2, Name = "Task 2", Description = "Description for Task 2", RedirectUrl = "/task1" }, new TaskModel { Id = 3, Name = "Task 3", Description = "Description for Task 3", RedirectUrl = "/task1" }, // Add more tasks as needed }; } private async Task StartTask(TaskModel task) { await App.Current.MainPage.Navigation.PushAsync(new NewPage1("test") ); // navigationManager.NavigateTo(task.RedirectUrl,true); } }
NewPage1.xaml
<?xml version="1.0" encoding="utf-8" ?> <ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="MauiApp14.Components.NewPage1" Title="Survey" xmlns:pages="clr-namespace:MauiApp14.Components.Pages"> <StackLayout> <!-- Entry (TextBox) for user input --> <Entry x:Name="entryTextBox" Placeholder="Enter text here" /> <!-- BlazorWebView to display Blazor content --> <BlazorWebView x:Name="blazorWebView4" HostPage="wwwroot/index.html"> <BlazorWebView.RootComponents> <RootComponent Selector="#app" ComponentType="{x:Type pages:Counter}" /> </BlazorWebView.RootComponents> </BlazorWebView> </StackLayout> </ContentPage>
/task1 Blazor页面
@page "/task1" @using MauiApp14.Components.Layout @inject Radzen.DialogService DialogService @inject NavigationManager navigationManager @inject DataTransferService DataTransferService <div style="padding-bottom: 60px;"> <!-- Adjust padding-bottom as needed --> <div class="rz-p-0 rz-p-md-12"> <RadzenStack Orientation="Orientation.Horizontal" FlexWrap="FlexWrap.Wrap" Gap="1rem" class="rz-p-4 rz-mb-6"> <RadzenTimeline Orientation="@orientation" LinePosition="LinePosition.Start" style="--rz-timeline-line-width: 3px; --rz-timeline-line-color: var(--rz-info); --rz-timeline-axis-size: 72px; max-width: 600px; margin: 0 auto;"> <Items> @foreach (var step in Steps) { <RadzenTimelineItem PointVariant="Variant.Outlined" PointStyle="@step.PointStyle" PointShadow="@step.PointShadow"> <PointContent><RadzenIcon Icon="@step.Icon" /></PointContent> <ChildContent> <RadzenText TextStyle="TextStyle.Subtitle1" class="rz-m-0">Step @step.Id</RadzenText> <RadzenText TextStyle="TextStyle.Body2" class="rz-m-0">@step.Title</RadzenText> </ChildContent> </RadzenTimelineItem> } </Items> </RadzenTimeline> </RadzenStack> </div> @if (!isComplete) { <!-- Symptom Check Dialog --> <SymptomCheckDialog OnNext="HandleNext" /> } else { <MauiApp14.Components.Pages.Survey.Complete /> } <button class="btn btn-primary" @onclick="GoBack">@MyProperty</button> </div> @code { [Parameter] public string MyProperty { get; set; } private async Task GoBack() { // Navigate back to the previous page await App.Current.MainPage.Navigation.PopToRootAsync(); } public List<UserTask> Steps { get; set; } = new List<UserTask>(); private bool isComplete = false; protected override Task OnInitializedAsync() { MyProperty = DataTransferService.EntryText; return base.OnInitializedAsync(); } private void HandleNext() { isComplete = true; Steps.ForEach(step => { if (step.Title == "Complete Your Profile") { step.PointStyle = PointStyle.Warning; } else { step.PointStyle = PointStyle.Primary; } }); StateHasChanged(); // Refresh the UI to show the Complete component } Orientation orientation = Orientation.Horizontal; public class UserTask { public int Id { get; set; } public string Title { get; set; } public bool LeftOn { get; set; } = false; public string Icon { get; set; } public int PointShadow { get; set; } = 0; public PointStyle PointStyle { get; set; } = PointStyle.Info; } }
解决方案
要实现将"test"传递到/task1页面的MyProperty参数,可通过以下两种方式完成:
方式1:使用共享服务传递数据(推荐)
利用你已有的DataTransferService,通过服务在页面间共享数据:
1. 注册共享服务
确保DataTransferService在MauiProgram.cs中注册为单例:
builder.Services.AddSingleton<DataTransferService>();
2. 修改NewPage1代码后台
在NewPage1.xaml.cs中接收传入的值并存入服务,同时修改BlazorWebView加载/task1页面:
public partial class NewPage1 : ContentPage { private readonly DataTransferService _dataTransferService; public NewPage1(string passedValue, DataTransferService dataTransferService) { InitializeComponent(); _dataTransferService = dataTransferService; // 将传递的值存入服务 _dataTransferService.EntryText = passedValue; // 替换原有RootComponent为/task1页面 blazorWebView4.RootComponents.Clear(); blazorWebView4.RootComponents.Add(new RootComponent("#app", typeof(MauiApp14.Components.Pages.task1), null)); } }
3. 修改ListOfTask的跳转逻辑
通过依赖注入获取服务实例,创建NewPage1:
@inject IServiceProvider ServiceProvider private async Task StartTask(TaskModel task) { var dataService = ServiceProvider.GetRequiredService<DataTransferService>(); var newPage = new NewPage1("test", dataService); await App.Current.MainPage.Navigation.PushAsync(newPage); }
4. 保持/task1页面的初始化逻辑
/task1页面中已有的OnInitializedAsync代码可以直接使用,会自动从服务中获取值:
protected override Task OnInitializedAsync() { MyProperty = DataTransferService.EntryText; return base.OnInitializedAsync(); }
方式2:直接给Blazor组件传递参数
跳过服务,直接在初始化Blazor组件时传入参数:
1. 修改NewPage1代码后台
public partial class NewPage1 : ContentPage { public NewPage1(string passedValue) { InitializeComponent(); // 替换RootComponent并传递参数 blazorWebView4.RootComponents.Clear(); var parameters = new Dictionary<string, object> { { "MyProperty", passedValue } }; blazorWebView4.RootComponents.Add(new RootComponent("#app", typeof(MauiApp14.Components.Pages.task1), parameters)); } }
2. 修改ListOfTask的跳转逻辑
private async Task StartTask(TaskModel task) { var newPage = new NewPage1("test"); await App.Current.MainPage.Navigation.PushAsync(newPage); }
3. 调整/task1页面的初始化逻辑
注释掉从服务取值的代码,让Blazor自动绑定参数:
protected override Task OnInitializedAsync() { // MyProperty = DataTransferService.EntryText; // 注释此行 return base.OnInitializedAsync(); }
关键注意事项
- 必须确保NewPage1中的BlazorWebView加载的是/task1页面,而非原来的Counter页面,否则参数传递无效。
- 使用共享服务时,必须注册为单例或作用域,保证数据在页面间共享。
- 直接传参时,参数名必须与Blazor组件中
[Parameter]修饰的属性名完全一致(此处为MyProperty)。
内容的提问来源于stack exchange,提问作者ZCoder
相关产品推荐
相关产品推荐

