locked
Show and Hide an AppBar in Windows store apps using MVVM RRS feed

  • Question

  • Hello everybody !!

    I'm developping a Windows store app in c# using MVVM.

    I need to hide and show my bottomAppBar according to my current page.

    In order to do this, I developped a HomeVIew here is my code :

    HomeVIew.xaml :

    <Page
        x:Class="Mobipost.Views.HomeView"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="using:Mo.Views"
        xmlns:localVM="using:Mo.ViewModels"
        xmlns:convert="using:Mo.Converters"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d">
        <Page.DataContext>
            <localVM:HomeViewModel />
        </Page.DataContext>
        <Page.Resources>
            <convert:AppBarVisibilityConverter
                x:Key="DisplayAppBarConverter" />
        </Page.Resources>
        <Page.TopAppBar>
            <AppBar x:Name="topAppBar" Visibility="{Binding IsTopAppBarVisible, Converter={StaticResource DisplayAppBarConverter},Mode=TwoWay}">
                <Grid>
                    <StackPanel Orientation="Horizontal" HorizontalAlignment="Left">
                        <Button Style="{StaticResource RetourTdbAppBarButtonStyle}" Command="{Binding GoToTdbCommand}" />
                    </StackPanel>
                </Grid>
            </AppBar>
        </Page.TopAppBar>
        <Page.BottomAppBar>
            <AppBar x:Name="bottomAppBar" Padding="10,0,10,0" Visibility="{Binding IsBottomAppBarVisible, Converter={StaticResource DisplayAppBarConverter}}">
                <Grid>
                    <StackPanel Orientation="Horizontal" HorizontalAlignment="Left" x:Name="leftPanelAppBar">
                        <Button Style="{StaticResource FinAppBarButtonStyle}" Command="{Binding EndVisitCommand}" />
                        <Button Style="{StaticResource CRAppBarButtonStyle}" />
                    </StackPanel>
                    <StackPanel Orientation="Horizontal" HorizontalAlignment="Right" x:Name="rightPanelAppBar">
                        <Button Style="{StaticResource DocsAppBarButtonStyle}" IsEnabled="False" />
                        <Button Style="{StaticResource AvisAppBarButtonStyle}" />
                        <Button Style="{StaticResource NotesAppBarButtonStyle}" />
                    </StackPanel>
                </Grid>
            </AppBar>
        </Page.BottomAppBar>
        <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
            <Frame x:Name="rootFrame" />
        </Grid>
    </Page>

    HomeView.xaml.cs :

    using Commons.Navigation;
    using Windows.UI.Xaml.Controls;
    using Windows.UI.Xaml.Navigation;
    using Mo.ViewModels;
    // The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238
    namespace Mobipost.Views
    {
        /// <summary>
        /// An empty page that can be used on its own or navigated to within a Frame.
        /// </summary>
        public sealed partial class HomeView : Page
        {
            #region Properties
            /// <summary>
            /// rootPage
            /// </summary>
            private Page rootPage = null;
            #endregion Properties
            #region Accueil constructeur
            /// <summary>
            /// Constructeur
            /// </summary>
            public HomeView()
            {
                this.InitializeComponent();
                this.NavigationCacheMode = NavigationCacheMode.Disabled;
               
            }
            #endregion Accueil constructeur
            #region Method
            /// <summary>
            /// Invoked when this page is about to be displayed in a Frame.
            /// </summary>
            /// <param name="e">Event data that describes how this page was reached.  The Parameter
            /// property is typically used to configure the page.</param>
            protected override void OnNavigatedTo(NavigationEventArgs e)
            {
                rootPage = e.Parameter as Page;
                ViewService.Service.NavigationService.Initialized(this.rootFrame);
                
                ViewService.Service.NavigationService.NavigateTo(
                     ViewService.Service.GetView("GroupingOfPostPage"), this);
            }
            #endregion Method
        }
    }

    HomeViewModel.cs

    using Commons.ChronoService;
    using Commons.Logging;
    using Commons.Navigation;
    using Mo.Common.Constants;
    using System.Diagnostics;
    using System.Windows.Input;
    namespace Mobipost.ViewModels
    {
        /// <summary>
        /// View Model de la page Accueil
        /// </summary>
        public class HomeViewModel : ViewModelBase
        {
            #region Properties
            /// <summary>
            /// Retour sur la page des OTs
            /// </summary>
            public ICommand RetourOtViewCommand { get; private set; }
            /// <summary>
            /// Fin de la visite
            /// </summary>
            public ICommand EndVisitCommand { get; private set; }
            /// <summary>
            /// Go sur la page tableau de bord
            /// </summary>
            public ICommand GoToTdbCommand { get; private set; }
            #endregion Properties
            #region HomeViewModel constructeur
            /// <summary>
            /// Constructeur
            /// </summary>
            public HomeViewModel()
            {
              
                DisplayAppBar(this.IsBottomAppBarVisible, this.IsTopAppBarVisible);
                EndVisitCommand = CommandFactory.CreateCommand(EndVisit);
                GoToTdbCommand = CommandFactory.CreateCommand(GoToDashboard);
            }
            #endregion AccueilViewModel constructeur
            #region Method
            /// <summary>
            /// Appelée lors de la fin de la visite
            /// </summary>
            private async void EndVisit()
            {
                await LogService.WriteInFile(Constant.EndVisit);
                Stopwatch stopchrono = Chrono.Instance.GetChrono();
                stopchrono.Stop();
                Debug.WriteLine("Le temps écoulé est : {0}", stopchrono.Elapsed);
                await LogService.WriteInFile(Constant.GoBackWorkingOrder);
                ViewService.Service.NavigationService.NavigateTo(
                    ViewService.Service.GetView(Constant.WorkingOrderPage));
            }
            /// <summary>
            /// Appelée lors du Go sur la page tableau de bord
            /// </summary>
            private async void GoToDashboard()
            {
                await LogService.WriteInFile(Constant.GotoDashboard);
                
                ViewService.Service.NavigationService.NavigateTo(
                     ViewService.Service.GetView(Constant.DashboardPage));
            }
            #endregion Method
        }
    }

    Here is the code of my ViewModelBase.cs

    

    using System.ComponentModel;
    namespace Mo.ViewModels
    {
        /// <summary>
        /// View Model de base
        /// </summary>
        public class ViewModelBase : INotifyPropertyChanged
        {
            #region Properties
            /// <summary>
            /// Etat de la Bottom AppBar
            /// </summary>
            private bool _IsBottomAppBarVisible ;
            public bool IsBottomAppBarVisible
            {
                get { return _IsBottomAppBarVisible; }
                set
                {
                    _IsBottomAppBarVisible = value;
                    OnPropertyChanged("IsBottomAppBarVisible");
                }
            }
            /// <summary>
            /// Etat de la Top AppBar
            /// </summary>
            private bool _IsTopAppBarVisible;
            public bool IsTopAppBarVisible
            {
                get { return _IsTopAppBarVisible; }
                set
                {
                    _IsTopAppBarVisible = value;
                    OnPropertyChanged("IsTopAppBarVisible");
                }
            }
            /// <summary>
            /// Evènement PropertyChanged
            /// </summary>
            public event PropertyChangedEventHandler PropertyChanged;
            #endregion Properties
            #region Method
            /// <summary>
            /// Appelée lors d'un changement sur une propriété
            /// </summary>
            protected virtual void OnPropertyChanged(string propertyName)
            {
                if (this.PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
            /// <summary>
            /// Appelée sur chaque page pour changer l'état de la Tpo et Bottom AppBar
            /// </summary>
            public void DisplayAppBar(bool TopAppBar, bool BottomAppBar)
            {
                this.IsTopAppBarVisible = TopAppBar;
                this.IsBottomAppBarVisible = BottomAppBar;
            }
            #endregion Method
        }
    }

    When I call the DisplayAppBar method in an other page like that :

    using Commons.Logging;
    using Commons.Navigation;
    using Mo.Common.Constants;
    using Mo.Converters;
    using Mo.DataAccessTemp;
    using ServicesTemp.Mobipost;
    using System.Collections.ObjectModel;
    using System.Windows.Input;
    using Windows.Storage;
    namespace Mo.ViewModels
    {
        /// <summary>
        /// View Model de la page GroupingOfPost
        /// </summary>
        public class GroupingOfPostsViewModel : ViewModelBase
        {
            #region Properties
            /// <summary>
            /// Go sur la page Site
            /// </summary>
            public ICommand GoToSiteCommand { get; private set; }
            /// <summary>
            /// Return Collection of GroupingOfPosts
            /// </summary>
            public ObservableCollection<GroupingOfPosts> GroupingOfPosts
            {
                get
                {
                    return GroupingOfPostService.GetAllGroupingOfPosts;
                }
            }
            #endregion Properties
            #region GroupingOfPostViewModel constructeur
            /// <summary>
            /// Constructeur
            /// </summary>
            public GroupingOfPostsViewModel()
            {
                this.IsBottomAppBarVisible = true;
                this.IsTopAppBarVisible = true;
                DisplayAppBar(this.IsBottomAppBarVisible, this.IsTopAppBarVisible);
                GoToSiteCommand = CommandFactory.CreateCommand<GroupingOfPosts>(GoToWorkingOrderPage);
                //AppBarButton.displayAppBar(false);
                AppBarButton.addButton(Constant.FinAppBarButtonStyle, GoToSiteCommand);
                //AppBarButton.removeButton("SortieAppBarButtonStyle");
            }
            #endregion GroupingOfPostViewModel constructeur
            #region Method
            /// <summary>
            /// Appelée lors du Go sur la page Site
            /// <param name="GroupingOfPost"></param>
            /// </summary>
            private async void GoToWorkingOrderPage(GroupingOfPosts GroupingOfPost)
            {
                await LogService.WriteInFile(Constant.GroupingOfPostChoice + GroupingOfPost.Name.ToString());
                var item = GroupingOfPost.Id;
                var GroupingOfPostName = GroupingOfPost.Name;
                ApplicationData.Current.LocalSettings.Values[Constant.GroupingOfPostId] = item;
                ApplicationData.Current.LocalSettings.Values[Constant.GroupingOfPostName] = GroupingOfPostName;
                ViewService.Service.NavigationService.NavigateTo(
                     ViewService.Service.GetView(Constant.WorkingOrderPage), GroupingOfPost);
            }
            #endregion Method
        }
    }

    My problem is that the DisplayAppBar takes always the values of the HomeViewModel not to the values of GroupingOfPostViewModel.

    Somebody have some ideas?

    THanx


    • Edited by DiddyRennes Thursday, August 29, 2013 9:08 AM
    Thursday, August 29, 2013 9:04 AM

All replies

  • Hello

    Because your HomePage have HomeViewModel in DataContext. So this page know nothing about your GroupingOfPostsViewModel. You need to change this values in HomeViewModel object. You can do this from GroupingOfPostsViewModel by using static class named "Locator"(it just a class which create static objects of your viewmodels and use for pages DataContext binding) or use GalaSoftMvvmLight library and GalaSoft.MvvmLight.Messaging.IMessenger from this lib.



    • Edited by Oleg Kurzov Thursday, August 29, 2013 9:23 AM
    Thursday, August 29, 2013 9:20 AM
  • Do you have any sample please?

    I don't understand very well.

    Thursday, August 29, 2013 12:15 PM
  • Your second page have GroupingOfPostsViewModel in DataContext?
    • Edited by Oleg Kurzov Thursday, August 29, 2013 5:41 PM
    Thursday, August 29, 2013 5:41 PM
  • Yes my second page has GroupingOfPostsViewModel in DataContext
    Friday, August 30, 2013 8:11 AM
  • Hi,DiddyRennes

    In order to solve the problem more efficiently I need to clarify some information.

    First, do you create one view or two Views?

    Second, if you create one view, do you want to make one View to different ViewModels?

    If you want to make one view to different ViewModels, there a solution you can follow up:

    1. Create a Model with the same name like MyModel in both the HomeViewModel and GroupingOfPostViewModel.

    Set the Page of DataContext to bind to {Binding MyModel}.

    2. Pass a query parameter to the View that indicates the different Model to be used

    3. Based on that parameter in the constructor of your View switch the Page.DataContext between HomeViewModel and GroupingOfPostViewModel.

    Best Wishes!


    <THE CONTENT IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, WHETHER EXPRESS OR IMPLIED>
    Thanks
    MSDN Community Support

    Please remember to "Mark as Answer" the responses that resolved your issue. It is a common way to recognize those who have helped you, and makes it easier for other visitors to find the resolution later.

    Friday, August 30, 2013 1:26 PM
  • Hello Anne Jing !

    First, do you create one view or two Views?

    => I create 2 views : HomeView and GroupingOfPostsView

    The HomeView is a kind of MasterView.

    Hope it will help....thanx very much

    Monday, September 2, 2013 9:54 AM
  • Hi,DiddyRennes

    Please upload your full project in SkyDrive and share a link in forum. I want to test it to make

    sure the problem why occur!


    <THE CONTENT IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, WHETHER EXPRESS OR IMPLIED>
    Thanks
    MSDN Community Support

    Please remember to "Mark as Answer" the responses that resolved your issue. It is a common way to recognize those who have helped you, and makes it easier for other visitors to find the resolution later.



    • Edited by Anne Jing Wednesday, September 4, 2013 5:15 AM from
    Wednesday, September 4, 2013 1:36 AM