You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MAUI Shell中如何强制VerBarcosPage构造函数每次执行?

问题描述

我有如下XAML代码:

<Shell
    x:Class="ControlBarcos.AppShell"
    xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    xmlns:views="clr-namespace:ControlBarcos.Views"
    xmlns:local="clr-namespace:ControlBarcos"
    Shell.FlyoutBehavior="Flyout">
     <Shell.BackButtonBehavior>
        <BackButtonBehavior IsEnabled="True" IsVisible="True"/>
    </Shell.BackButtonBehavior>

    <Shell.ItemTemplate>
        <DataTemplate>
            <Grid ColumnDefinitions="0.2*,0.8*">
                <Image Source="{Binding Icon}"
                       Margin="5"
                       HeightRequest="25"
                       WidthRequest="25"/>
                <Label Grid.Column="1"
                       Text="{Binding Title}"
                       FontAttributes="Bold"
                       FontSize="Large"
                       VerticalTextAlignment="Center" /> 
            </Grid>
        </DataTemplate>
    </Shell.ItemTemplate>
    <ShellContent ContentTemplate="{DataTemplate views:InicialPage}" />
    <FlyoutItem Title="Barcos"
                Icon="shipdos.png">
       <Tab>
           <ShellContent ContentTemplate="{DataTemplate views:VerBarcosPage}" />
       </Tab>
    </FlyoutItem>
    <FlyoutItem Title="Empresas Externas"
                Icon="humano.png">
       <Tab>
           <ShellContent ContentTemplate="{DataTemplate views:VerEmpresasPage}" />
       </Tab>
    </FlyoutItem>
</Shell>

InicialPage仅用于显示logo。首次选择“Barcos”菜单选项时,VerBarcosPage的构造函数会被调用,但再次选择该选项时,构造函数不会执行。我需要让该构造函数每次都被调用,请问有什么解决方法?

VerBarcosPage的代码如下:

public partial class VerBarcosPage : ContentPage
{
    public VerBarcosViewModel viewModel;

    public VerBarcosPage()
    {
        InitializeComponent();
        viewModel = new VerBarcosViewModel();
        BindingContext = viewModel;
    }
}
解决方法

MAUI Shell默认会缓存页面实例,重复点击菜单不会重新创建页面,因此不会触发构造函数。以下是几种实现每次点击都触发构造函数的方案:

方案一:动态绑定创建新页面实例

修改Shell中ShellContent的定义,用属性绑定替代DataTemplate,每次访问属性时返回新的页面实例:

  1. 在AppShell后台代码中添加属性:
public VerBarcosPage VerBarcosPage => new VerBarcosPage();
public VerEmpresasPage VerEmpresasPage => new VerEmpresasPage();
  1. 修改XAML中的ShellContent节点:
<FlyoutItem Title="Barcos" Icon="shipdos.png">
   <Tab>
       <ShellContent Content="{Binding Source={RelativeSource AncestorType={x:Type local:AppShell}}, Path=VerBarcosPage}" />
   </Tab>
</FlyoutItem>
<FlyoutItem Title="Empresas Externas" Icon="humano.png">
   <Tab>
       <ShellContent Content="{Binding Source={RelativeSource AncestorType={x:Type local:AppShell}}, Path=VerEmpresasPage}" />
   </Tab>
</FlyoutItem>

每次点击菜单时,会调用属性的getter创建新页面实例,构造函数随之执行。

方案二:监听导航事件移除缓存页面

在AppShell中监听导航事件,导航前移除目标页面的缓存实例,迫使Shell重新创建页面:

  1. 在AppShell构造函数中添加事件监听:
public AppShell()
{
    InitializeComponent();
    Navigating += AppShell_Navigating;
}

private void AppShell_Navigating(object sender, ShellNavigatingEventArgs e)
{
    // 处理VerBarcosPage导航
    if (e.Target.Location.OriginalString.Contains(nameof(VerBarcosPage)))
    {
        var existingPage = Current.Items.FirstOrDefault(item => item.Content is VerBarcosPage);
        if (existingPage != null)
        {
            Current.Items.Remove(existingPage);
        }
    }
    // 同理处理VerEmpresasPage
    else if (e.Target.Location.OriginalString.Contains(nameof(VerEmpresasPage)))
    {
        var existingPage = Current.Items.FirstOrDefault(item => item.Content is VerEmpresasPage);
        if (existingPage != null)
        {
            Current.Items.Remove(existingPage);
        }
    }
}

方案三:将初始化逻辑移至页面显示事件

如果不需要重建页面,仅需每次进入页面时执行初始化操作,可将构造函数中的逻辑迁移至Appearing事件:

修改VerBarcosPage代码:

public partial class VerBarcosPage : ContentPage
{
    public VerBarcosViewModel viewModel;

    public VerBarcosPage()
    {
        InitializeComponent();
        Appearing += VerBarcosPage_Appearing;
    }

    private void VerBarcosPage_Appearing(object sender, EventArgs e)
    {
        viewModel = new VerBarcosViewModel();
        BindingContext = viewModel;
        // 其他需每次进入执行的逻辑
    }
}

这种方式无需修改Shell配置,适合仅需重置数据而非重建页面的场景。

内容的提问来源于stack exchange,提问作者user1803086

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 04:01:04