.NET MAUI:自定义Shell TitleView并绑定到当前页面标题

问题描述 投票:0回答:3
.net maui .net-maui.shell
3个回答
2
投票

作为替代方案,您可以在 OnNaviged 方法中设置 titleview :

在 AppShell.xaml 中,定义标签的名称

<Shell.TitleView>
    <Grid ColumnDefinitions="*,200">
        <Label BindingContext="{x:Reference shellMain}" x:Name="mylabel" FontSize="Large" TextColor="White" />
        <ActivityIndicator IsRunning="{Binding IsBusy}" Color="Orange" Grid.Column="1" HorizontalOptions="End" />
    </Grid>
</Shell.TitleView>

在AppShell.xaml.cs中,重写OnNaviged方法,获取当前项目

protected override void OnNavigated(ShellNavigatedEventArgs args)
{
    base.OnNavigated(args);

    var shellItem = Shell.Current?.CurrentItem;
    string title = shellItem?.Title;
    int iterationCount = 0;
    while (shellItem != null
        && title == null)
    {
        title = shellItem.Title;
        shellItem = shellItem.CurrentItem;

        if (iterationCount > 10)
            break;  // max nesting reached

        iterationCount++;
    }

    myLabel.Text = title;
}

希望它对你有用。


0
投票

我正在尝试同样的方法来修改 TitleView 的外观。它可以在 iOS 上运行,尽管那里还有另一个错误。但在 Android 上我遇到了同样的问题。在前进导航中,它会更新标题,但当您按后退按钮时,标题不会更新。我已经打开了一个问题并添加了一个存储库。

https://github.com/dotnet/maui/issues/12416#issuecomment-1372627514

还有其他方法可以修改TitleView的外观吗?


0
投票

我使用视图模型开发了这个解决方法,主要不是为了提供 MVVM 解决方案,而是因为其他建议的答案对我不起作用。 (我怀疑 Liqun Shen 2 月 15 日针对他自己的问题的评论中的建议会起作用。但我没有注意到这一点,直到我自己修复)。

当前页面的标题保存在可由 shell 的视图模型和每个内容页面的视图模型访问的类中:

public class ServiceHelper {
    private static ServiceHelper? _default;
    public static ServiceHelper Default => _default ??= new ServiceHelper();
    internal string CurrentPageTitle { get; set; } = string.Empty;
}

shell 中每个内容页面的视图模型提供其页面标题。为了促进这一点,大部分工作都是由基本视图模型完成的,它们都是从该模型派生而来的:

public abstract class ViewModelBase(string title) : ObservableObject {
    private ServiceHelper? _serviceHelper;
    public string Title { get; } = title;

    internal ServiceHelper ServiceHelper {
        get => _serviceHelper ??= ServiceHelper.Default;
        set => _serviceHelper = value; // For unit testing.
    }

    public virtual void OnAppearing() {
        ServiceHelper.CurrentPageTitle = Title;
    }
}

每个 shell 内容页面视图模型只需要让其基础视图模型知道它的标题:

public class LocationsViewModel : ViewModelBase {
    public LocationsViewModel() : base("Locations") {
    }
}

每个 shell 内容页面都需要在其视图模型中触发所需的事件响应方法:

public partial class LocationsPage : ContentPage {
    private LocationsViewModel? _viewModel;

    public LocationsPage() {
        InitializeComponent();
    }

    private LocationsViewModel ViewModel => 
        _viewModel ??= (LocationsViewModel)BindingContext;

    protected override void OnAppearing() {
        base.OnAppearing();
        ViewModel.OnAppearing();
    }
}

Shell 的视图模型为标题栏提供当前页面的标题:

public class AppShellViewModel() : ViewModelBase(Global.ApplicationTitle) {
    private string _currentPageTitle = string.Empty;

    public string CurrentPageTitle {
        get => _currentPageTitle;
        set {
            _currentPageTitle = value;
            OnPropertyChanged();
        }
    }

    public void OnNavigated() {
        CurrentPageTitle = ServiceHelper.CurrentPageTitle;
    }
}

Shell 需要在其视图模型中触发所需的事件响应方法:

public partial class AppShell : Shell {
    private AppShellViewModel? _viewModel;

    public AppShell() {
    InitializeComponent();
    }

    private AppShellViewModel ViewModel => 
    _viewModel ??= (AppShellViewModel)BindingContext;

    protected override void OnNavigated(ShellNavigatedEventArgs args) {
        base.OnNavigated(args);
        ViewModel.OnNavigated();
    }
}

最后,Shell 的 XAML 在标题栏/导航栏上显示由 Shell 视图模型提供的当前页面的标题:

<Shell.TitleView>
    <HorizontalStackLayout  VerticalOptions="Fill">
        <Image Source="falcon_svg_repo_com.png"
               HeightRequest="50"/>
        <Label x:Name="CurrentPageTitleLabel"
               Text="{Binding CurrentPageTitle}"
               FontSize="24"
               Margin="10,0"
               VerticalTextAlignment="Center"/>
    </HorizontalStackLayout>
</Shell.TitleView>
© www.soinside.com 2019 - 2024. All rights reserved.