XAML 带有Query属性的.NET MAUI Shell导航不总是加载页面

6bc51xsx  于 2023-04-27  发布在  .NET
关注(0)|答案(2)|浏览(192)

我正在创建一个简单的桌面应用程序。该应用程序将在弹出窗口中有三个项目,弹出窗口是锁定的。弹出窗口中的第一个项目将路由到它自己的页面。然而,后两个页面基本上是相同的(相同的内容页面/视图模型),但是需要向它传递动态信息。但是当我选择飞出式项目时,应用程序并不总是加载正确的页面。
具体而言,行为如下:

  • 应用程序加载时选中并显示UniquePage。
  • 我单击弹出型“变体1”。
  • 应用程序加载VariantPage和databinds标题到我传递的查询作为显示。
  • 我单击弹出选项2。
  • 应用程序加载VariantPage和databinds标题到我传递的查询作为显示。
  • 单击弹出按钮唯一。
  • 应用程序加载时选中并显示UniquePage。
  • 我点击变量1。
  • 应用程序仍保留上一页UniquePage。所有后续选择仍保留此页。

我正在使用CommunityToolkit. Mvvmnuget包。
从我的AppShell.xaml:

<FlyoutItem  Title="Unique">
    <Tab>
        <ShellContent
            ContentTemplate="{DataTemplate local:MVVM.View.UniquePage}"
            Route="UniquePage" />
    </Tab>
</FlyoutItem>
<FlyoutItem Title="Variant 1">
    <Tab>
        <ShellContent
            ContentTemplate="{DataTemplate local:MVVM.View.VariantPage}"
            Route="VariantPage?Side=Test1" />
    </Tab>
</FlyoutItem>
<FlyoutItem  Title="Variant 2">
    <Tab>
        <ShellContent
            ContentTemplate="{DataTemplate local:MVVM.View.VariantPage}"
            Route="VariantPage?Side=Test2" />
    </Tab>
</FlyoutItem>

在AppShell.xaml的backing.cs文件中,我使用nameof()typeof()注册到每个页面的路由。
VariantPage的ViewModel:

[QueryProperty(nameof(Side), nameof(Side))]
public partial class VariantViewModel : BaseViewModel
{
    public ObservableCollection<Widget> Widgets{ get; } = new();
    ConfigurationService configService;

    [ObservableProperty]
    private string side = "Left";

    public VariantViewModel(ConfigurationService service)
    {
        this.configService = service;
        LoadWidgets();
    }

    private void LoadWidgets()
    {
        //assigns stuff to Widgets
    }
}

BaseViewModel继承自ObservableObject。VariantPage的备份看起来像这样:

public VariantPage(VariantViewModel viewModel)
{
    BindingContext = viewModel;
    InitializeComponent();
}

protected override void OnNavigatedTo(NavigatedToEventArgs args)
{
    base.OnNavigatedTo(args);
}

最后,MauiProgram.cs builder正在注册以下内容:

builder.Services.AddSingleton<ConfigurationService>();
builder.Services.AddSingleton<VariantViewModel>();
builder.Services.AddSingleton<VariantPage>();
builder.Services.AddSingleton<UniqueViewModel>();
builder.Services.AddSingleton<UniquePage>();

任何关于如何获得一致行为的建议或解释将不胜感激。

z31licg0

z31licg01#

这里有一个解决方法。重写OnNavigation方法并使用MessagingCenter更改Side的值。您可以尝试以下代码:
在AppShell.cs中,每次导航时发布一条消息:

protected override void OnNavigating(ShellNavigatingEventArgs args)
{
    base.OnNavigating(args);

    if (args.Target.Location.OriginalString.Contains("VariantPage1"))
    {

        MessagingCenter.Send<AppShell, string>(this, "Hi", "Test1");
    }

    if (args.Target.Location.OriginalString.Contains("VariantPage2"))
    {
        MessagingCenter.Send<AppShell, string>(this, "Hi", "Test2");
    }
}
  • 路由可以在FlyoutItem、TabBar、Tab和ShellContent对象上通过其Route属性定义。* 因此,您不必再在AppShell.cs中注册。
<FlyoutItem Title="Variant 1">
    <Tab>
        <ShellContent
            ContentTemplate="{DataTemplate local:VariantPage}"        
            Route="VariantPage1">
        </ShellContent>
        </Tab>
</FlyoutItem>
<FlyoutItem Title="Variant 2">
    <Tab>
        <ShellContent
            ContentTemplate="{DataTemplate local:VariantPage}"
            Route="VariantPage2" />
        </Tab>
</FlyoutItem>

对于VariantViewModel,订阅消息

[ObservableProperty]
    private string side = "Left";

    public VariantViewModel(ConfigurationService service)
    {
        this.configService = service;
        LoadWidgets();
        MessagingCenter.Subscribe<AppShell, string>(this, "Hi", (sender, arg) =>
        {
            Side = arg;
        });
    }

有关详细信息,请参阅Publish and subscribe to messages
希望能成功。

z2acfund

z2acfund2#

我不知道从何说起。
这个“单例”既用于ViewModel也用于View。尝试在 shell XAML中传递参数。在构造函数中加载小部件。
我会给予你你问的变通办法,但你正在走向更大的问题。
首先:你可以覆盖OnNavigating。(这在你的shell代码中)检查你的event.Target.Location。根据你导航到的位置,设置你想要的数据到你的ViewModel。
第二:你可以覆盖OnNavigatedTo。(这在你的Page中,但可以作为命令传递给ViewModel)检查你的Shell.Current.CurrentState.Location。设置你想要的数据。
你可以时不时地检查一下:https://github.com/dotnet/maui/issues/3868

相关问题