Xamarin Forms MessagingCenter Подписка вызывается два раза

Я нажимаю на элемент продукта в просмотре списка в модели представления страницы продукта, чтобы показать всплывающее окно (используя всплывающее окно rg.plugin) для выбора одного из вариантов продукта. После выбора варианта я отправляю выбранный вариант на страницу продукта с помощью центра обмена сообщениями из варианта всплывающая страница viewmodel, подписанная в конструкторе viewmodel страницы продукта. там нормально работает. Когда я перехожу на предыдущую страницу и затем возвращаюсь на эту страницу продукта для добавления одного или нескольких вариантов к одному и тому же ранее выбранному продукту,Messagingcenter вызывается дважды, и стоимость продукта увеличивается вдвое. Попытка подписаться на странице продукта при появлении а отпишись в пропавшем методе. еще два раза звонишь? Как решить эту проблему?

вызов всплывающего окна:

               var result = await dataService.Get_product_variant(store_id, product_id);
                if (result.status == "success")
                {
                    ind_vis = false;
                    OnPropertyChanged("ind_vis");

                    App.Current.Properties["product_variant_result"] = result;
                    App.Current.Properties["cartitems"] = purchaselist;
                    App.Current.Properties["selected_product"] = product_List2 ;
                    await PopupNavigation.Instance.PushAsync(new Popup_variant());                   
                }

popup viewmodel: отправка сообщения

        public Popup_variant_vm()
        {
            Radio_btn = new Command<Product_variant_list2>(Radio_stk_tapped);
            product_variant_list = new List<Product_variant_list2>();
            purchaselist = new ObservableCollection<Product_list2>();                       
            show_variants();            
        }

        internal void Confirm_variant()
        {
            if(App.Current.Properties.ContainsKey("selected_variant"))
            {
                 MessagingCenter.Send<Popup_variant_vm, object>(this, "selected_variant", App.Current.Properties["selected_variant"]); //Message send from popup to product page                    
            }
            else
            {
                DependencyService.Get<IToast>().LongAlert("Please select any size");
            }
        }

модель просмотра страницы продукта: подписана здесь.. вызывается дважды при переходе с предыдущей страницы на эту

    public Store_page()
    {
       InitializeComponent();
    }
    protected override void OnAppearing()
    {
        base.OnAppearing();

        var vm = new store_page_vm();
        vm.Navigation = Navigation;
        BindingContext = vm;

        MessagingCenter.Unsubscribe<Popup_variant_vm, object>(this, "selected_variant");
        MessagingCenter.Subscribe<Popup_variant_vm, object>(this, "selected_variant",async (sender, selected_variant) =>
        { 
            var vm1 = BindingContext as store_page_vm;
            vm1?.Addcart2(selected_variant);// called twice
        });            
    } 

отписался на странице товара cs

protected override void OnDisappearing()
        {
            var vm = BindingContext as store_page_vm;
            vm?.Save_cart();    
            MessagingCenter.Unsubscribe<Popup_variant_vm>(this, "selected_variant");    
        }

5 ответов

Решение

Ваша отписка должна выглядеть примерно так, как показано ниже, и она должна работать:

  MessagingCenter.Unsubscribe<Popup_variant_vm, object>(this, "selected_variant");

Изменение Messagingcenter на единую подписку.

      public class Messagingcenter_singleton
{
    private static Messagingcenter_singleton _instance;
    private bool isActivated = false;
    private Action<string> callBackFun = null;
    public static Messagingcenter_singleton Instance()
    {
        if (_instance == null)
        {
            _instance = new Messagingcenter_singleton();
        }
        return _instance;
    }

    public void setCallBack(Action<string> eventCallBack)
    {
        callBackFun = eventCallBack;
    }

    public void startSubscribe()
    {
        if (!isActivated)
        {
            isActivated = true;
            MessagingCenter.Subscribe<string, string>(this, "Name", eventCallBack);
        }
    }

    private void eventCallBack(string arg1, string arg2)
    {
        if (callBackFun != null)
        {
            InvokeMethod(new Action<string>(callBackFun), arg2);
        }
    }

    public static object InvokeMethod(Delegate method, params object[] args)
    {
        return method.DynamicInvoke(args);
    }

}

Используйте код ниже в своем классе модели

      public void initSubscribe()
{
   Messagingcenter_singleton.Instance().startSubscribe();
   Messagingcenter_singleton.Instance().setCallBack(eventCallBack)
}

public void eventCallBack(string arg2)
{
// write your code here
}

Мое решение:

поместите предложение отказа от подписки в тело подписки!!

 MessagingCenter.Subscribe<object, string>(this, "IdSearch", (sender, arg) =>
            {
              

                listView.ItemsSource = arg;

                MessagingCenter.Unsubscribe<object, string>(this, "IdSearch");

            }, BindingContext);

/questions/33234601/forma-xamarin-otmena-podpiski-messagingcenter-ne-rabotaet-dolzhnyim-obrazom/33234607#33234607

попробуйте это, и убедитесь, что вы не звоните подписаться более одного раза.

Я создал статическую переменную счетчика в своем приложении в подписчике, который я сделал:

      
public static class Constants
{
    public static int msgCenterSubscribeCounter { get; set; } = 0;
}

MessagingCenter.Subscribe<object, string>(this, "hello", (sender, arg) =>
{
    Constants.msgCenterSubscribeCounter++;
    if (arg.Equals("hello") && Constants.msgCenterSubscribeCounter == 1)  
    {
        // handle your logic here
    }
});

Сбросить счетчик в методе OnDisappearing(), откуда вы вызвали Send.

Другие вопросы по тегам