【问题标题】:How to refresh page from left menu如何从左侧菜单刷新页面
【发布时间】:2020-09-30 02:55:44
【问题描述】:

Xamarin forms Using MVVM..Used burger example to have left hand side menu.

    //MainPage
    [XamlCompilation(XamlCompilationOptions.Compile)]
        public partial class MainPage : MasterDetailPage
        {
            int idOfNewPage;
            Dictionary<int, NavigationPage> MenuPages = new Dictionary<int, NavigationPage>();
            public MainPage()
            {
                InitializeComponent();
    
                MasterBehavior = MasterBehavior.Popover;
    
                MenuPages.Add((int)MenuItemType.Products, (NavigationPage)Detail);
            }
    
            public async Task NavigateFromMenu(int id)
            {
                if (!MenuPages.ContainsKey(id))
                {
                    switch (id)
                    {
                        case (int)MenuItemType.Products:
                            MenuPages.Add(id, new NavigationPage(new ProductPage()));
                            break;
                        case (int)MenuItemType.Shopping:
                            MenuPages.Add(id, new NavigationPage(new ShoppingPage()));
                            break;
                        case (int)MenuItemType.Browse:
                            MenuPages.Add(id, new NavigationPage(new ItemsPage()));
                            break;
                        case (int)MenuItemType.About:
                            MenuPages.Add(id, new NavigationPage(new AboutPage()));
                            break;
                    }
    
                    idOfNewPage = id;
                }
    
                idOfNewPage = id;
    
                var newPage = MenuPages[id];
    
                if (newPage != null)
                {
                    Detail = newPage;
    
                    if (Device.RuntimePlatform == Device.Android)
                        await Task.Delay(100);
    
                    IsPresented = false;
                }
            }
    }
    
     [XamlCompilation(XamlCompilationOptions.Compile)]
        public partial class MenuPage : ContentPage
        {
            MainPage RootPage { get => Application.Current.MainPage as MainPage; }
            List<HomeMenuItem> menuItems;
        
            public MenuPage()
            {
                InitializeComponent();
    
                menuItems = new List<HomeMenuItem>
                {
                    new HomeMenuItem {Id = MenuItemType.Products, Title="Products", Icon =  "back_nav.png", Name = "test" },
                    new HomeMenuItem {Id = MenuItemType.ShoppingCart, Title="Shopping Cart", Icon =  "back_nav.png"},
                    new HomeMenuItem {Id = MenuItemType.Browse, Title="Browse", Icon =  "back_nav.png"},
                    new HomeMenuItem {Id = MenuItemType.About, Title="About", Icon =  "back_nav.png"}
                };
    
                ListViewMenu.ItemsSource = menuItems;
       
                ListViewMenu.ItemSelected += async (sender, e) =>
                {
                    if (e.SelectedItem == null)
                     return;
    
                    var id = (int)((HomeMenuItem)e.SelectedItem).Id;
                    var MenuBtnClicked = (string)((HomeMenuItem)e.SelectedItem).Title;
    
    
                    await RootPage.NavigateFromMenu(id);
    
                    ListViewMenu.SelectedItem = null;
                };
            }
}

所以这一切都很好,我可以使用左侧的菜单从页面跳回和第四个。 然而,问题在于shoppingPage。

产品页面上显示产品的列表视图。(下)如果用户更改产品的数量,则调用 WineQuantityChanged()。更新屏幕上的数量 并调用 - UpdateShoppingCartItems()。它将产品添加到 DrinksToPurchaseList 中。 现在,当用户单击购物车图标(作为工具栏项添加,而不是从菜单中添加)时,代码调用 ShoppingClicked() 使用 DrinksToPurchase 列表填充 App.globalShoppingCartOC 并加载购物车页面。

        //ProductPage.cs
     public ProductPage()
            {
            
              PopulateQuantityPicker();
    
                InitializeComponent();
                
                  productPage_ViewModal = new ProductPageViewModel();
                  
                   NoItemsInShoppingCart.Text = App.NoOfItemsInShoppingCartGlobalVar;
                   
                     BindingContext = productPage_ViewModal;
                     
                     }
                     
            
            
            
            private async void ShoppingClicked(object sender, EventArgs e)
            {
                 //global list storing up to date products and quantites
                App.globalShoppingCartOC = DrinksToPurchase;
                await RootPage.NavigateFromMenu(1);
            }
            
  void WineQuantityChanged(object sender, EventArgs e)
        {
            var picker = (Picker)sender;
            int newQuantity = picker.SelectedIndex;
            string winePickerId = picker.Id.ToString();
            int oldQuantity = -1;
            int tempDiffOfValues = 0;
            var product = (ProductModel)picker.BindingContext;
//code to update quantity 

//update shopping cart items
                UpdateShoppingCartItems(product, newQuantity);
                NoItemsInShoppingCart.Text = quantityOfProducts.ToString();
                App.NoOfItemsInShoppingCartGlobalVar = quantityOfProducts.ToString();

           }
        }


        //update item in shopping cart with new quantity
        void UpdateShoppingCartItems(ProductModel product, int quantity)
        {

            if (!DrinksToPurchaseList.Contains(product))
            {
                product.Quantity = quantity;
                DrinksToPurchaseList.Add(product);
            }
            else
            {
                ProductModel result = DrinksToPurchaseList.Where(x => x.ProductId == product.ProductId).FirstOrDefault();

                if (result != null)
                {
                    //remove from list
                    if (quantity < 1)
                    {
                        DrinksToPurchaseList.Remove(result);
                    }
                    else // else update new quantity
                    {
                        result.Quantity = quantity;
                    }
                }
            }
        }
            
            
            //ProductPage.xaml
            
             <ToolbarItem x:Name="NumberOfItemsInShoppingCart" Priority="0" Order="Primary" Activated="ShoppingClicked"/>
            
             <StackLayout Grid.Row="2">
                <Button Text="Wine" Clicked="WineClicked" WidthRequest="100" HorizontalOptions="Start"/>
                <ListView ItemsSource="{Binding WineList}" x:Name="WineListView" IsVisible="False" HasUnevenRows="True" SeparatorVisibility="None" VerticalOptions="FillAndExpand" VerticalScrollBarVisibility="Always" HeightRequest="1500">
                    <ListView.ItemTemplate>
                        <DataTemplate>
                            <ViewCell>
                               
                                <Grid x:Name="Wine" RowSpacing="25">
                                    <Grid.RowDefinitions>
                                        <RowDefinition Height="Auto"/>
                                        <RowDefinition Height="*"/>
                                    </Grid.RowDefinitions>
                                    <Grid.ColumnDefinitions>
                                        <ColumnDefinition Width="Auto"/>
                                        <ColumnDefinition Width="*"/>
                                    </Grid.ColumnDefinitions>
                                    <Label Grid.Column="0" Grid.Row="0" Text="{Binding ProductId}" VerticalOptions="End" IsVisible="False"/>
                                    <controls:CircleImage  Grid.Column="1"  Grid.Row="0" HeightRequest="60" HorizontalOptions="CenterAndExpand" VerticalOptions="Center" Aspect="AspectFill" WidthRequest="66" Grid.RowSpan="2" Source="{Binding Image}"/>
                                    <Label Grid.Column="2" Grid.Row="0" Text="{Binding ProductName}" VerticalOptions="Start"/>
                                    <Label Grid.Column="2" Grid.Row="0"  Text="{Binding Description}" VerticalOptions="End"/>
                                    <Label Grid.Column="3" Grid.Row="0" VerticalOptions="Start" Text="{Binding Price, StringFormat='£{0:0.00}'}"/>
                                    <Picker Grid.Column="4" Grid.Row="0" SelectedIndexChanged="WineQuantityChanged" SelectedIndex="{Binding Quantity}">
                                        <Picker.Items>
                                            <x:String>0</x:String>
                                            <x:String>1</x:String>
                                            <x:String>2</x:String>
                                            <x:String>3</x:String>
                                            <x:String>4</x:String>
                                            <x:String>5</x:String>
                                            <x:String>6</x:String>
                                        </Picker.Items>
                                    </Picker>
                                </Grid>
                            </ViewCell>
                        </DataTemplate>
                    </ListView.ItemTemplate>
                </ListView>

从购物车页面,用户还可以更改商品的数量,调用 QuantityChanged()-> 调用 UpdateShoppingCartItems() 并使用 ShoppingCartViewModel.ShoppingCartList(保存新数量)重新填充 App.globalShoppingCartOC 例如,他们更改数量,然后返回产品页面(从左侧菜单)。

(应该在 ProductPage 上调用 OnAppearing())并重新加载 VM?

    public ShoppingCartPage ()
            {
                InitializeComponent();
    
                if (App.globalShoppingCartOC != null)
                {
                    foreach (ProductModel Model in App.globalShoppingCartOC)
                    {
                        if (Model.Quantity > 0)
                        {
//populate LV with global shopping OC
                            Model.SubTotalForItem = Model.Quantity * Model.Price;
                            ShoppingCartViewModel.ShoppingCartList.Add(Model);//ShoppingCartList is the ListView on xaml
                            TotalForAllItems += Model.SubTotalForItem;
                        }
                    }
                }
    
                this.BindingContext = this;
                BindingContext = ShoppingCartViewModel;
            }
    
         void QuantityChanged(object sender, EventArgs e)
            {
    //updates correct quantity on screen and calls
    //UpdateShoppingCartItems()
    }
    
        //update item in shopping cart with new quantity
            void UpdateShoppingCartItems(ProductModel product, int quantity)
            {
                ProductModel result = ShoppingCartViewModel.ShoppingCartList.ToList().Find(x => x.ProductId == product.ProductId);
    
                if (result != null)
                {
                    //remove from list
                    if (quantity < 1)
                    {
                        ShoppingCartViewModel.ShoppingCartList.Remove(result);
                    }
                    else // else update new quantity
                    {
                        result.Quantity = quantity;
                    }
                }
    
                App.globalShoppingCartOC = ShoppingCartViewModel.ShoppingCartList;
            }
    
        //xaml
          <StackLayout Grid.Row="0">
    
                <ListView ItemsSource="{Binding ShoppingCartList}" HasUnevenRows="True" SeparatorVisibility="None">
                    <ListView.Header>
                        <Button Text="Place Order" Clicked="OrderPlaced_BtnClicked"/>
                    </ListView.Header>
                    <ListView.Footer>
                        <Label x:Name="TotalForItems" HorizontalTextAlignment="End" VerticalTextAlignment="Start" Margin="20,20" FontAttributes="Bold"/>
                    </ListView.Footer>
                    <ListView.ItemTemplate>
                        <DataTemplate>
                            <ViewCell>
    
                                <Grid x:Name="ShoppingCartGrid" RowSpacing="25" ColumnSpacing="10">
                                    <Grid.RowDefinitions>
                                        <RowDefinition Height="Auto"/>
                                        <RowDefinition Height="*"/>
                                    </Grid.RowDefinitions>
                                    <Grid.ColumnDefinitions>
                                        <ColumnDefinition Width="Auto"/>
                                        <ColumnDefinition Width="*"/>
                                    </Grid.ColumnDefinitions>
    
                                    <Label Grid.Column="0" Text="{Binding Id}" VerticalOptions="End" IsVisible="False"/>
                                    <controls:CircleImage  Grid.Column="1"  Grid.Row="1" HeightRequest="60" HorizontalOptions="CenterAndExpand" VerticalOptions="CenterAndExpand" Aspect="AspectFill" WidthRequest="66" Grid.RowSpan="2" Source="{Binding Image}"/>
                                    <Label Grid.Column="2" Grid.Row="1" Text="{Binding ProductName}" VerticalOptions="End"/>
                                    <Label Grid.Column="2" Grid.Row="2" VerticalOptions="Start" Text="{Binding Description}"/>
                                    <Label Grid.Column="3" Grid.Row="2" VerticalOptions="Start" Text="{Binding Price, StringFormat='£{0:0.00}'}"/>
    
                                    <Picker Grid.Column="4" Grid.Row="2" VerticalOptions="Start" SelectedIndexChanged="QuantityChanged" SelectedIndex="{Binding Quantity}">
                                        <Picker.Items>
                                            <x:String>0</x:String>
                                            <x:String>1</x:String>
                                            <x:String>2</x:String>
                                            <x:String>3</x:String>
                                            <x:String>4</x:String>
                                            <x:String>5</x:String>
                                            <x:String>6</x:String>
                                        </Picker.Items>
                                    </Picker>
    
                                </Grid>
                            </ViewCell>

现在,我需要从 productPage_ViewModal.WineList 重新加载“WineList”中的所有产品并遍历 App.globalShoppingCartOC,更新任何新数量。

问题是我可以单步执行并且 OnAppearing 会这样做,但是当页面重新加载时,它会显示原始数量,从用户第一次从产品页面移动到购物车页面。 (所以存储在drinksToOrder 中的数量)

修改

更新代码以在 ProductPage 中包含 OnAppearing

protected override void OnAppearing()
    {
        base.OnAppearing();
        
        if (App.globalShoppingCartOC != null)
        {
            if (App.globalShoppingCartOC.Count > 0)
            {
                 foreach(var item in App.globalShoppingCartOC)
                {
                    if(item.Genre == "Wine")
                    {
                        productPage_ViewModal.WineList.Where(x => x.ProductId == item.ProductId).FirstOrDefault().Quantity = item.Quantity;
                    }
                }

                 WineListView.ItemsSource = productPage_ViewModal.WineList;
                 
                  this.BindingContext = this.productPage_ViewModal;
                  
                            }
        }
    }

因此,我可以看到我已经在 productPage_ViewModal.WineList 和 WineListView.ItemsSource 中更新了正确数量的项目

然后又累到bindingContext了……但是从购物车页面返回后页面仍然加载原始的DrinksToPurchaseList

这是为什么?为什么我不能刷新大众来更新?

【问题讨论】:

  • 如果实际问题出在 ProductsPage 上,显示该页面的代码会很有帮助。一般来说,我建议每次访问页面时使用 OnAppearing 刷新数据。或者,您可以在页面之间使用公共 VM
  • 杰森感谢您的回复。我已经包含 ProductsPage 的代码,现在我已经添加了 OnAppearing,它在从购物车返回到产品页面时被调用。我可以看到 Listview 的 VM 和 itemSource 已更新,但它仍然在屏幕上显示旧的 obseravableCollection - DrinksToOrder ....请参阅 Q 的更新以包含此谢谢...任何建议?
  • “仍然显示旧的 obseravableCollection”和“仍然加载原始的 DrinksToPurchaseList” - 根据您发布的代码,我不知道其中任何一个是什么。
  • 对不起 - 我现在也发布了 ShoppingCart 代码......并添加了更好的解释
  • 这真的没有回答我的任何一个问题。如果您能够在某处发布您的解决方案,我可以快速查看一下

标签: c# xaml xamarin xamarin.forms


【解决方案1】:
Create an event on master page, invoke event from master page in your case blog and consume that event on another page where you want to refresh data..
on master page what you've to do is..
declare event..
public delegate void refreshDelegate();
public static event  refreshDelegate refreshEvent;
__
now invoke this event,
  refreshEvent?.inovke();

now,
   on the page where you want to refresh data, at constructor access the declared event,
masterpage.refreshEvent+=masterpage_refreshEvent;  
   private void masterpage_refreshEvent()
  { 
BindData();
}
       
now, bind the data in invoked event, it'll refresh your screen as expected.  

【讨论】:

    猜你喜欢
    • 2022-01-10
    • 1970-01-01
    • 1970-01-01
    • 2011-05-04
    • 2021-10-11
    • 2012-05-23
    • 2019-10-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多