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);
попробуйте это, и убедитесь, что вы не звоните подписаться более одного раза.
Я создал статическую переменную счетчика в своем приложении в подписчике, который я сделал:
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.