.Net Maui: MVVM如何使用Shell导航捕获来自不同页面的返回

3
我已经使用Shell GoToAsync导航设置了一个主页和详细页导航。
[RelayCommand] 
public async void SelectionChanged() //Friend friend
{
    if (SelectedItem == null) return;

    Friend f = SelectedItem;

    Console.WriteLine($"Selection made {f.FName} {f.LName}");

    //navigate
    var navigationParameter = new Dictionary<string, object>
    {
        { "Friend", f }
    };
    await Shell.Current.GoToAsync(nameof(DetailPage), true, navigationParameter);

    //remove selection highlight
    SelectedItem = null;
}

这个可以工作。但是,我不知道如何在我的主页面中捕获从详细页面返回的内容,因为我需要刷新我的CollectionView和底层的sqlite数据存储。

我大多数时候都遵循了Gerald Versluis的视频:https://www.youtube.com/watch?v=pBh5SXVSwXw

有什么建议吗?

非常感谢,G


1
也许使用消息发布/订阅? - ToolmakerSteve
你能告诉我你的返回数据在哪里吗?你想从哪里获取这些数据?如何在主页面中捕获详细页面的返回数据? - Jessie Zhang -MSFT
1
我不需要返回的数据,因为那部分已经正常工作了。我只需要在从我的DetailPage导航回MainPage时捕获某种事件。从文档中我看到有一个Shell.BackButtonBehaviour可以链接到ViewModel中的命令,但是我需要在单击某个按钮并导航回来时触发其他事件。这样我就可以在MainPage中重新排序我的ObservableCollection(其中包含更改的数据)了。 :) - gfmoore
我现在(有点)明白你的意思了,@ToolmakerSteve。谢谢。 - gfmoore
4个回答

1
事实证明,这并不像看起来的那么难。@ToolmakerSteve 指出了一个解决方案,但当时我并不理解。解决方案就是简单地使用 MessagingCenter 方法。文档 https://learn.microsoft.com/en-us/dotnet/maui/fundamentals/messagingcenter 对用法并不十分清晰,但是根据 https://codemilltech.com/messing-with-xamarin-forms-messaging-center/ 中的注释进行了调整,我做了以下操作。
在我的详细页面 ViewModel 和返回主页面的按钮中(而不是我还没有捕获的“返回”按钮)。 (使用 MVVM 辅助程序版本 8.0.0.0 预览版 4(不是 7,但可以适应).
[RelayCommand]
public async void ReturnMainPage()
{
  MessagingCenter.Send(new MessagingMarker(), "IDidSomething");
}

在 MainPageViewModel 中的构造函数中。
public MainPageViewModel()
{
  ...
  MessagingCenter.Subscribe<MessagingMarker>(this, "IDidSomething", (s) => {
    //do something in response to the detail page changing something
  });
  ...
}


希望这对未来的某个人有所帮助。 顺便问一下,“this”是指什么?页面吗?根据代码位置,“this”可能不合适,还能放什么? 另外,您也可以使用“this”传递对象,可以参考我在.Net Maui: How to read/write (get/set) a global object from any content page (MVVM)中的问题。

1
thisSubscribing 对象。只有当您不再需要消息时,它才有意义;您将拥有相应的 Unsubscribe,使用相同的 this。它可以是任何唯一于此订阅的对象(多个对象可以订阅同一消息),并且方便取消订阅。 - ToolmakerSteve

0

0
如果我需要在点击某个按钮并返回时触发其他事件,该怎么办呢?
如果您想在返回时执行某些操作,可以使用BackButtonBehavior来实现。
如果您想在单击某个按钮并返回时触发其他事件,可以尝试以下代码:
 await Shell.Current.GoToAsync("..");

而且可以将带有“..”的后退导航与路由结合使用:

 await Shell.Current.GoToAsync("../route");

更多信息,请查看:反向导航


谢谢,是的,那就是我要做的事情,但是我该如何拦截或劫持回调到主页面,以便我可以完成我的任务? - gfmoore
点击一个按钮时,您可以添加自己的代码。 - Jessie Zhang -MSFT
是的,但那只是在详细页面上,而我需要对显示的列表进行重新排序的是主页面。这两个上下文是不同的。我无法从详细页面访问主页面中的列表,否则生活会变得轻松得多。也许你知道一个方法? - gfmoore
当向后导航时,数据可以通过查询属性传递:await Shell.Current.GoToAsync($"..?parameterToPassBack={parameterValueToPassBack}") - Ignotus

0

MessagingCenter在.NET 7中已被弃用,并由CommunityToolkit.Mvvm NuGet包中的WeakReferenceMessenger替代。有关更多信息,请参阅docs

在您的主页面上:

public class MessageModel() {
    public string Message {get;set;}
}

public MasterPage() {

   ...

   WeakReferenceMessenger.Default.Register<MessageModel>(this, (r, m) =>
   {
     // do something, reload view 
   });
}

当你返回时,在您的详细页面上:

MessageModel messagemodel = new() {
    Message = "IDidSomething"
};
WeakReferenceMessenger.Default.Send(messagemodel);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接