在视图模型之间使用时,MessagingCenter退订在xamarin表单中不起作用

时间:2018-11-20 10:41:08

标签: c# android xaml xamarin xamarin.forms

我正在处理Xamarin Forms。在视图模型之间使用时,退订在MessagingCenter中不起作用。

我正在尝试退订messagingCenterOnDisappear()上的ContentPage。我要取消订阅的原因是,当我进行订阅时,它计为两次,并且消息也发送了两次。它最多只能收到1次,与订阅相同。在我的代码下面。

BottomTabsViewModel的订阅位置:

   using RCBazaar.Base.ViewModels;
using RCBazaar.Services.Interfaces;
using RCBazaar.ViewModels.Base;
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Text;
using System.Windows.Input;
using Xamarin.Forms;

namespace RCBazaar.ViewModels
{
    public class BottomTabsViewModel : ViewModelBase
    {
        public ICommand HomeCommand => new Command(HomeTab_Clicked);
        public ICommand CategoriesCommand => new Command(CategoriesTab_Clicked);
        public ICommand CartCommand => new Command(CartTab_Clicked);
        public ICommand ChatCommand => new Command(ChatTab_Clicked);
        private string _badgeText;
        private bool _isActiveHome;
        public bool IsActiveHome
        {
            get
            {
                return _isActiveHome;
            }
            set
            {
                _isActiveHome = value;
                RaisePropertyChanged(() => IsActiveHome);
            }
        }

        private bool _isActiveCategory;
        public bool IsActiveCategory
        {
            get
            {
                return _isActiveCategory;
            }
            set
            {
                _isActiveCategory = value;
                RaisePropertyChanged(() => IsActiveCategory);
            }
        }

        private bool _isActiveCart;
        public bool IsActiveCart
        {
            get
            {
                return _isActiveCart;
            }
            set
            {
                _isActiveCart = value;
                RaisePropertyChanged(() => IsActiveCart);
            }
        }

        private bool _isActiveChat;
        public bool IsActiveChat
        {
            get
            {
                return _isActiveChat;
            }
            set
            {
                _isActiveChat = value;
                RaisePropertyChanged(() => IsActiveChat);
            }
        }

        public string BadgeText
        {
            get
            {
                return _badgeText;
            }
            set
            {
                _badgeText = value;
                RaisePropertyChanged(() => BadgeText);
            }
        }



        public static string IsSelected { get; set; }



        public BottomTabsViewModel()
        {


            BadgeCount();


            if (IsSelected == "Home")
            {
                ActiveHome();
            }
            else if (IsSelected == "Category")
            {
                ActiveCategory();
            }
            else if (IsSelected == "Cart")
            {
                ActiveCart();
            }
            else if (IsSelected == "Chat")
            {
                ActiveChat();
            }
            else
            {
                ActiveHome();
            }
        }

        private void BadgeCount()
        {

            //Subscriber listen for the specific message. Here getting data for refresh the listView when add item to the database.
            MessagingCenter.Subscribe<ProductDetailsViewModel, string>(this, "ShoppingCartCount", (sender, arg) =>
            {
                try
                {
                    if (arg != null)
                    {
                        BadgeText = arg;
                    }
                }
                catch (Exception ex)
                {
                }
            });
        }


        public void HomeTab_Clicked()
        {
            IsSelected = "Home";
            NavigationService.NavigateToAsync<HomeProductsViewModel>();
        }

        public void CategoriesTab_Clicked()
        {
            IsSelected = "Category";
            NavigationService.NavigateToAsync<MainCategoriesListViewModel>();
        }

        public void CartTab_Clicked()
        {
            IsSelected = "Cart";
            NavigationService.NavigateToAsync<AccordianViewModel>();
        }

        public void ChatTab_Clicked()
        {
            IsSelected = "Chat";
            NavigationService.NavigateToAsync<RCBazaarInformationViewModel>("Contact us");
        }

        public void ActiveHome()
        {
            IsActiveHome = true;
            IsActiveCategory = false;
            IsActiveCart = false;
            IsActiveChat = false;
        }

        public void ActiveCategory()
        {
            IsActiveHome = false;
            IsActiveCategory = true;
            IsActiveCart = false;
            IsActiveChat = false;
        }

        public void ActiveCart()
        {
            IsActiveHome = false;
            IsActiveCategory = false;
            IsActiveCart = true;
            IsActiveChat = false;

        }
        public void ActiveChat()
        {
            IsActiveHome = false;
            IsActiveCategory = false;
            IsActiveCart = false;
            IsActiveChat = true;
        }


    }
}

** ProductDetailViewModel发送消息的地方:**

 using FFImageLoading.Forms;
using Plugin.Share;
using Plugin.Share.Abstractions;
using RCBazaar.Base.ViewModels;
using RCBazaar.Model.ShoppingCart;
using RCBazaar.Services.Interfaces;
using RCBazaar.Services.Products;
using RCBazaar.ViewModels;
using RCBazaar.Views;
using Rg.Plugins.Popup.Services;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
using Xamarin.Forms;

[assembly: Dependency(typeof(ProductDetailsViewModel))]
namespace RCBazaar.ViewModels
{
    public class ProductDetailsViewModel : ViewModelBase
    {
        private Product _productDetails;
        private string _productName;
        private long _productStock;
        private double _productPrice;
        private string _productDescription;
        private ObservableCollection<string> _productImage;
        private string _productSKU;
        private ObservableCollection<CartItem> _basketItems;
        private Color _badgeColor;

        private long _productId;

        private string _overviewColor;
        private string _reviewsColor;
        private bool _productDescriptionIsVisible;
        private long _productRating;
        private string _badgeText;


        public ProductDetailsViewModel()
        {
            try
            {


                BasketItems = new ObservableCollection<CartItem>();

                BadgeText = "0";
                OverviewColor = "#231f20";//blue color
                ReviewsColor = "#DCDCDC";//lightgray
                ProductDescriptionIsVisible = true;
                ReviewIsVisible = false;
              //  _navigation = navigation;




                var images = new List<string>() { "CourselStaticImage3.jpeg", "CourselStaticImage2.jpeg", "CourselStaticImage1.jpeg", "CourselStaticImage4.jpeg" };

                ProductImage = new ObservableCollection<string>(images);



                OnRatingChanged();

                MyCommand = new Command(() =>
                {
                    Debug.WriteLine("Position selected.");
                });

                int[] numbers = new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
                List<WareHouse> wareHouses = new List<WareHouse>()
                {
                    new WareHouse {WarehouseId=1, WareHouseName= "Banglore outlet", Items= numbers },
                    new WareHouse {WarehouseId=2, WareHouseName= "Pune outlet", Items= numbers },
                    new WareHouse {WarehouseId=3, WareHouseName= "Mumbai outlet", Items= numbers }
                };

                ListHeight = wareHouses.Count * 30;

                WareHouses = new ObservableCollection<WareHouse>(wareHouses);

                Reviews = new ObservableCollection<Review> { new Review { ReviewTitle="title",ReviewText="text",rating=2,IsReviewHelpful=true},
                new Review { ReviewTitle="title",ReviewText="text",rating=4,IsReviewHelpful=false},
                new Review { ReviewTitle="title",ReviewText="text",rating=0,IsReviewHelpful=true},
                new Review { ReviewTitle="title",ReviewText="text",rating=2,IsReviewHelpful=true},
                new Review { ReviewTitle="title",ReviewText="text",rating=4,IsReviewHelpful=false},
                new Review { ReviewTitle="title",ReviewText="text",rating=0,IsReviewHelpful=true},
                new Review { ReviewTitle="title",ReviewText="text",rating=2,IsReviewHelpful=true},
                new Review { ReviewTitle="title",ReviewText="text",rating=4,IsReviewHelpful=false},
                new Review { ReviewTitle="title",ReviewText="text",rating=0,IsReviewHelpful=true},
                };

            }

            catch (Exception ex)
            {

            }
        }
        public class Review
        {
            public string id { get; set; }
            public string ReviewTitle { get; set; }
            public string ReviewText { get; set; }
            public float rating { get; set; }
            public string CreatedDate { get; set; }
            public bool IsReviewHelpful { get; set; }
        }

        private ObservableCollection<Review> _reviews;
        public ObservableCollection<Review> Reviews
        {
            get
            {
                return _reviews;
            }
            set
            {
                _reviews = value;
                RaisePropertyChanged(() => Reviews);
            }
        }

        public override async Task InitializeAsync(object navigationData)
        {

            _productDetails = (Product)navigationData;
            ProductName = _productDetails.Name;
            ProductStock = _productDetails.Qtyonhand;
            ProductPrice = _productDetails.pricelist;
            ProductDescription = _productDetails.FullDescription;
            ProductRating = _productDetails.RatingSum;
            //   ProductImage = _productDetails.PictureBinary;
            ProductId = _productDetails.ProductId;
            ProductSKU = _productDetails.upc;
            //// Update Basket/badgecount
            //var basket = await _basketService.GetBasketAsync(userInfo.UserId, authToken);

            //if (basket != null && basket.Items != null && basket.Items.Any())
            //{
            //    BadgeCount = 0;
            //    BasketItems.Clear();

            //    foreach (var basketItem in basket.Items)
            //    {
            //        BadgeCount += basketItem.Quantity;
            //        await AddBasketItemAsync(basketItem);
            //    }
            //}
        }
        //private async Task AddBasketItemAsync(BasketItem item)
        //{
        //    BasketItems.Add(item);
        //    await ReCalculateTotalAsync();
        //}

        public ICommand ItemSelectedCommand => new Command(async () =>
        {
            try
            {
                WarehouseItemSelected = null;
            }
            catch (Exception ex)
            {

            }

        });

        public string BadgeText
        {
            get
            {
                return _badgeText;
            }
            set
            {
                _badgeText = value;
                RaisePropertyChanged(() => BadgeText);
            }
        }


        public ICommand AddtoCartCommand => new Command(async(e)=> await AddItemAsync(e));
        private async Task AddItemAsync(object e)
        {
            try
            {                 
                var value = int.Parse(BadgeText);

                if (value < 10)
                {

                    BadgeText = (++value).ToString();
                    //BadgeColor = Color.FromHex("#000000");
                    //await Task.Delay(3000);
                    //BadgeColor = Color.FromHex("#FF9933");
                }
                else
                    BadgeText = "0";

                MessagingCenter.Send(this, "ShoppingCartCount", BadgeText);
                var selectedItem = (ProductDetailsViewModel)e;

                await AddBasketItemAsync(selectedItem);
                RaisePropertyChanged(() => BasketItems);
            }
            catch (Exception ex)
            {
              await  App.Current.MainPage.DisplayAlert("Alert!", "Something went wrong!..", "Ok");
            }
        }

        public Color BadgeColor
        {
            get
            {
                return _badgeColor;
            }
            set
            {
                _badgeColor = value;
                RaisePropertyChanged(() => BadgeColor);
            }
        }
        private async Task AddBasketItemAsync(ProductDetailsViewModel selectedItem)
        {
            try
            {
                // BasketItems.Add(selectedItem); this can be used if BasketItems is of type productdetauilsviewmodel
                BasketItems.Add(new CartItem { BasketProductId = ProductId, WarehouseDetails = WareHouses });

                await ReCalculateTotalAsync();
            }
            catch (Exception ex)
            {
              await  App.Current.MainPage.DisplayAlert("Alert!", "Something went wrong!..", "Ok");
            }
        }
        private async Task ReCalculateTotalAsync()
        {
            //Total = 0;

            //if (BasketItems == null)
            //{
            //    return;
            //}

            //foreach (var orderItem in BasketItems)
            //{
            //    Total += (orderItem.Quantity * orderItem.UnitPrice);
            //}

            //var authToken = _settingsService.AuthAccessToken;
            //var userInfo = await _userService.GetUserInfoAsync(authToken);

            //await _basketService.UpdateBasketAsync(new CustomerBasket
            //{
            //    BuyerId = userInfo.UserId,
            //    Items = BasketItems.ToList()
            //}, authToken);
        }

        //public ICommand AddtoCartCommand => new Command(async () =>
        //{
        //    var value = int.Parse(BadgeText);

        //    if (value < 10)
        //        BadgeText = (++value).ToString();
        //    else
        //        BadgeText = "0";
        //    MessagingCenter.Send(this, "ShoppingCartCount", BadgeText);
        //});
        public ObservableCollection<CartItem> BasketItems
        {
            get { return _basketItems; }
            set
            {
                _basketItems = value;
                RaisePropertyChanged(() => BasketItems);
            }
        }
        private int _listHeight;


        public int ListHeight
        {
            get
            {
                return _listHeight;
            }
            set
            {
                _listHeight = value;
                RaisePropertyChanged(() => ListHeight);
            }
        }

        private WareHouse _warehouseItemSelected;
        public WareHouse WarehouseItemSelected
        {
            get
            {
                return _warehouseItemSelected;
            }
            set
            {
                _warehouseItemSelected = value;
                RaisePropertyChanged(() => WarehouseItemSelected);


            }
        }

        public class WareHouse
        {
            public int WarehouseId{ get; set; }
            public string WareHouseName { get; set; }
            public int[] Items { get; set; }
            public int quantity { get; set; }
        }

        private ObservableCollection<WareHouse> _wareHouses;
        public ObservableCollection<WareHouse> WareHouses
        {
            get
            {
                return _wareHouses;
            }
            set
            {
                _wareHouses = value;
                RaisePropertyChanged(() => WareHouses);
            }
        }



        public long ProductRating
        {
            get
            {
                return _productRating;
            }
            set
            {
                _productRating = value;
                RaisePropertyChanged(() => ProductRating);


            }
        }
        public long ProductId
        {
            get
            {
                return _productId;
            }
            set
            {
                _productId = value;
                RaisePropertyChanged(() => ProductId);


            }
        }

        public ObservableCollection<string> ProductImage
        {
            get
            {
                return _productImage;
            }
            set
            {
                _productImage = value;
                RaisePropertyChanged(() => ProductImage);
            }
        }
        public string ProductName
        {
            get
            {
                return _productName;
            }
            set
            {
                _productName = value;
                RaisePropertyChanged(() => ProductName);
            }
        }
        public long ProductStock
        {
            get
            {
                return _productStock;
            }
            set
            {
                _productStock = value;
                RaisePropertyChanged(() => ProductStock);


            }
        }
        public double ProductPrice
        {
            get
            {
                return _productPrice;
            }
            set
            {
                _productPrice = value;
                RaisePropertyChanged(() => ProductPrice);


            }
        }
        public string ProductSKU
        {
            get
            {
                return _productSKU;
            }
            set
            {
                _productSKU = value;
                RaisePropertyChanged(() => ProductSKU);


            }
        }
        public string OverviewColor
        {
            get
            {
                return _overviewColor;
            }
            set
            {
                _overviewColor = value;
                RaisePropertyChanged(() => OverviewColor);


            }
        }
        public string ReviewsColor
        {
            get
            {
                return _reviewsColor;
            }
            set
            {
                _reviewsColor = value;
                RaisePropertyChanged(() => ReviewsColor);


            }
        }
        public string ProductDescription
        {
            get
            {
                return _productDescription;
            }
            set
            {
                _productDescription = value;
                RaisePropertyChanged(() => ProductDescription);


            }
        }
        public bool ProductDescriptionIsVisible
        {
            get
            {
                return _productDescriptionIsVisible;
            }
            set
            {
                _productDescriptionIsVisible = value;
                RaisePropertyChanged(() => ProductDescriptionIsVisible);


            }
        }

        private bool _reviewIsVisible;
        public bool ReviewIsVisible
        {
            get
            {
                return _reviewIsVisible;
            }
            set
            {
                _reviewIsVisible = value;
                RaisePropertyChanged(() => ReviewIsVisible);


            }
        }

        public Command MyCommand { protected set; get; }
        public ICommand AddReviewCommand => new Command(async () =>
        {
            try
            {
                // await push.Instance.PopAllAsync();
                await PopupNavigation.Instance.PushAsync(new ReviewPopUpView());
                //await _navigation.PushAsync(new ReviewPopUpView());

            }

            catch (Exception ex)
            {

            }
        });
        public ICommand ShareCommand => new Command(async () =>
        {
            try
            {
                await CrossShare.Current.Share(new ShareMessage
                {
                    Text = "Please download RcBazaar app from playstore",
                    Title = "Share Product",
                    Url = "http://rcbazaar.com/product.aspx?productid=6863"
                });

            }

            catch (Exception ex)
            {

            }
        });
        private void OnRatingChanged()
        {
            try
            {

                //Subscriber listen for the specific message. Here getting data for refresh the listView when add item to the database.
                MessagingCenter.Subscribe<ProductsView, float>(this, "ProductsPage", (sender, arg) =>
                {
                    if (arg != null)
                    {

                        Rating = arg;
                    }

                });
            }

            catch (Exception ex)
            {

            }
        }
        private float _rating;
        public float Rating
        {
            get
            {
                return _rating;
            }
            set
            {
                _rating = value;
                RaisePropertyChanged(() => Rating);
            }
        }
        public ICommand ViewImageCommand => new Command(async (parameter) => await ViewImage((string)parameter));

        public async Task ViewImage(string ImageName)
        {
            try
            {


                await NavigationService.NavigateToAsync<ImageFullScreenViewModel>(ImageName);


            }

            catch (Exception ex)
            {

            }
        }
        public ICommand OverviewCommand => new Command(async () =>
        {
            try
            {


                OverviewColor = "#231f20";//blue color
                ReviewsColor = "#DCDCDC";//lightgray
                ProductDescriptionIsVisible = true;
                ReviewIsVisible = false;

            }

            catch (Exception ex)
            {

            }
        });
        public ICommand ReviewsCommand => new Command(async () =>
        {
            try
            {
                OverviewColor = "#DCDCDC";//lightgray
                ReviewsColor = "#231f20";//blue color

                ProductDescriptionIsVisible = false;
                ReviewIsVisible = true;

            }

            catch (Exception ex)
            {

            }
        });

    }
}

主页消失时退订:

   using FFImageLoading.Work;
using RCBazaar.CustomRenderer;
using RCBazaar.Helpers;
using RCBazaar.ViewModels;
using RCBazaar.Views.NavigationBarWithSideDrawer;
using Rg.Plugins.Popup.Services;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using Xamarin.Forms;
using Xamarin.Forms.Xaml;

namespace RCBazaar.Views
{
    [XamlCompilation(XamlCompilationOptions.Compile)]
    public partial class HomeView : ContentPage
    {


        public HomeView()
        {

            try
            {
                InitializeComponent();

                NavigationPage.SetHasNavigationBar(this, false);

                //BindingContext = new HomeProductsViewModel(this.Navigation);

            }
            catch (Exception ex)
            {
                App.Current.MainPage.DisplayAlert(Constants.ConstantKeys.Alert, Constants.ConstantKeys.UIError, Constants.ConstantKeys.Ok);
            }
        }


        protected override void OnDisappearing()
        {
            base.OnDisappearing();
            MessagingCenter.Unsubscribe<SortingOptionsViewModel>(this, "UpdateHomeList");
            MessagingCenter.Unsubscribe<ProductDetailsViewModel, string>(this, "ShoppingCartCount");
        }

        protected override void OnAppearing()
        {
            base.OnAppearing();
            MessagingCenter.Unsubscribe<ProductDetailsViewModel, string>(this, "ShoppingCartCount");
        }

    }
}

2 个答案:

答案 0 :(得分:0)

您要在ViewModel中订阅您想要的 MessagingCenter 事件,但是您要在视图中取消订阅。当用户调用MessagingCenter.Subscribe时,用户传递了该类的实例,他们希望回调进入。

由于您正在视图中调用取消订阅,并将Views实例传递给取消订阅,因此ViewModel永远都不会被取消订阅,这将导致在您导航回到此页面时产生额外的事件调用。

我建议您不要在视图中调用MessagingCenter.Unsubscribe,而应在 ViewModel 上调用方法以从MessagingCenter退订。

HomeView.cs

protected override void OnDisappearing()
{
    base.OnDisappearing();

    ViewModel.Disappearing(); // Method to unsubscribe from MessagingCenter in ViewModel
}

HomeProductsViewModel.cs

public void Disappearing()
{
    // Unsubscribe from events here because this is the class where you register them
    MessagingCenter.Unsubscribe<SortingOptionsViewModel>(this, "UpdateHomeList");
    MessagingCenter.Unsubscribe<ProductDetailsViewModel, string>(this, "ShoppingCartCount");
}

答案 1 :(得分:0)

基于共享代码的一些建议:

  1. 订阅OnAppearing,然后取消订阅OnDisappearing。目前,您正在订阅构造函数。
  2. MessagingCenter.Subscribe第一个参数是对将要侦听消息的对象的引用,如果您想MessagingCenter.Unsubscribe,则应使用相同的引用。取消订阅对您不起作用,因为您订阅了视图模型并取消了页面的订阅。

有关MessagingCenter的更多信息可以在the official documentation中找到。