【问题标题】:How to use Messaging center in xamarin forms如何在 xamarin 表单中使用消息中心
【发布时间】:2021-04-04 17:05:00
【问题描述】:

我正在尝试在 xamarin 表单中使用消息中心而不是 Messenger 我不知道消息中心我尝试使用 Bellow 代码以 xamarin 表单订阅和发送消息

MessagingCenter.Send(this, "TodoTable", "Todo");

但我不知道从哪里可以订阅此消息,我尝试了以下代码:

MessagingCenter.Subscribe<TodoClass>(this, Todo, async (sender, arg) =>
{
  await RefreshCommand.ExecuteAsync();
});

这给了我错误任何帮助将不胜感激:)

【问题讨论】:

标签: xamarin xamarin.forms


【解决方案1】:

这是 XF 消息中心的一个怪癖,(似乎)您需要知道谁将发送消息,以及可能谁将接收消息。

但是它可以是对象。 subscribe的签名是:

void MessagingCenter.Subscribe<TSender>(object subscriber, string message, Action<TSender> callback, TSender sender = null)

诀窍是这样订阅:

MessagingCenter.Subscribe<object>(this, "messageName", Action<object> callback)

这表示对象或从对象派生的任何东西都可以是发送者,即一切。

但是,如果您只想订阅由某个类型的特定实例发送的消息:

MessagingCenter.Subscribe<MyClass>(this, "messageName", Action<MyClass> callback)

使用完整签名有点可疑。基本上它是说只有从源对象发送的订阅者是在订阅时使用该源对象的订阅者。

  MessagingCenter.Subscribe<object, string>(this, "Hi", 
      (sender, arg) =>
      {
        DisplayAlert("Message Received", "arg=" + arg, "OK");
      },
      BindingContext);

如果您使用以下方式发送消息,上面的订阅者将不会收到它:

  MessagingCenter.Send<object, string>(this, "Hi", "John");

但是会收到以下内容

  MessagingCenter.Send<object, string>(BindingContext, "Hi", "John");

虽然你为什么要给自己发消息。 (假设在这种情况下订阅和发送在同一个页面中)。

但是,如果有多个页面具有完全相同的绑定上下文,则消息将发送给所有此类订阅者。例如,绑定到相同视图模型的页面。

【讨论】:

    【解决方案2】:

    为了改进@user2825546 的回答,如果您希望只订阅来自视图模型的消息,您需要在发送消息时指定基类类型:

    MessagingCenter.Subscribe<BaseViewModel, string>(this, "ShowError", (view, message) => { });
    
    public class StartupViewModel : BaseViewModel
    {
         //Like this...
         MessagingCenter.Send<BaseViewModel, string>(this, "ShowError", "Message");
         //Or...
         MessagingCenter.Send((BaseViewModel)this, "ShowError", "Message");
    }
    

    在测试时,我尝试以StartupViewModel 发送消息,但监听器没有收到消息。我猜它会,因为该类派生自BaseViewModel

    【讨论】:

      【解决方案3】:

      MVVM 的目标是从业务逻辑中抽象出视图。这确保了出色的代码重用、可测试性,并且非常棒。许多 MVVM 框架提供了增强此功能的工具,例如数据绑定和依赖服务,以使我们的生活更轻松。这些内置在 Xamarin.Forms 中,非常棒,但少有人提及的功能是消息中心。它的全部目标是使 ViewModel 或其他组件能够相互通信,而无需了解彼此的任何信息,除了一个简单的消息合约。

      例如,假设您处于主/详细信息设置中,您的 MasterViewModel 有一个项目列表,而您的 DetailViewModel 允许您创建新项目、更新项目或删除项目。当您的用户在详细信息页面上并触发了一个事件时,您需要以某种方式向具有项目列表的 MasterViewModel 发送消息,以便当我们返回时 UI 可以在母版页面上做出反应。

      假设我们的 MasterViewModel 订阅了“Update”和“AddNew”消息事件。然后它会根据收到消息的时间来更新它的 observable 集合。然后,我们的 DetailViewModel 将在 SaveCommand 中发送一条消息,以通知订阅这些特定消息的任何人:

        public ObservableCollection<TripExpense> Expenses { get; set; }
      
       public ExpensesViewModel()
       { 
         Expenses = new ObservableCollection<TripExpense>();
      
         //Subscibe to insert expenses
         MessagingCenter.Subscribe<TripExpense>(this, "AddNew", (expense) =>
         {
           Expenses.Add(expense);
         });
      
         //subscribe to update expenxes
         MessagingCenter.Subscribe<TripExpense>(this, "Update", (expense) =>
         {
           ExecuteUpdateExpense(expense);
         });
       }
      
      
      
      
       private async Task ExecuteSaveCommand()
          {
        if (IsBusy)
          return;
      
        IsBusy = true;
      
        //Send a message to insert/update the expense to all subscribers
        if(isNew)
        {
          MessagingCenter.Send(expense, "AddNew");
        }
        else
        {
          MessagingCenter.Send(expense, "Update");
        }
        IsBusy = false;
        navigation.PopAsync();
      }
      

      你有它,消息传递变得容易!如果您不想再收到通知,请不要忘记取消订阅。

      【讨论】:

      • 但是接收方必须知道发送方的类型。我想这已经知道很多了。有没有办法避免指定发件人的类型? “对象”似乎不起作用。
      • 伟大的复制\粘贴工作伙伴 ;) montemagno.com/how-to-use-xamarinforms-messaging-center
      • 从 James Montemagno 复制/粘贴的答案
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-13
      • 2019-11-01
      • 2021-12-18
      相关资源
      最近更新 更多