How to share a BottomAppBar with multiple pages in WP 8.1 - xaml

My app have multiple pages and I want all of them to have the same bottom app bar
Here's the code for my bottom app bar:
<Page.BottomAppBar>
<CommandBar ClosedDisplayMode="Minimal" Background="#FF004557">
<CommandBar.SecondaryCommands>
<AppBarButton x:Name="AppBar_1" Label="AppBar_1" Click="AppBar_1_Click"/>
<AppBarButton x:Name="AppBar_2" Label="AppBar_2" Click="AppBar_2_Click" />
<AppBarButton x:Name="AppBar_3" Label="Appbar_3" Click="AppBar_3_Click" />
<AppBarButton Label="About" />
</CommandBar.SecondaryCommands>
</CommandBar>
</Page.BottomAppBar>
How do I do it?

Okay.
When your app runs the first time the first thing that executes is the OnLaunched method in your App.xaml.cs file. It probably looks like this:
protected override void OnLaunched(LaunchActivatedEventArgs e)
{
Frame rootFrame = Window.Current.Content as Frame;
if (rootFrame == null)
{
rootFrame = new Frame();
Window.Current.Content = rootFrame;
}
if (rootFrame.Content == null)
{
rootFrame.Navigate(typeof(MainPage), e.Arguments);
}
Window.Current.Activate();
}
Navigation in Windows 8 is handled by the navigation framework which is a lot like a browser. If you call the browser a frame than you get it. There is one frame and pages load inside it. You can load another page, then go back in the frame like you would go back in a browser to get to the previous page. And, like your browser has history, your Windows 8 XAML frame has a backstack to accomplish this. You can also go forward.
That OnLaunched code creates the first frame in your app (since there is not one there by default) and sets it to the Windows.Current.Content which is the native UI container for all apps. Specifically, it's the line Window.Current.Content = rootFrame;.
From this point forward, pages in your app, including your MainPage are loaded inside this new root frame. This is the typical implementation for a Windows 8 app. This changes with a shared app bar. A shared app bar does not set Window.Current.Content to a frame but instead sets it to a root page that has a frame inside it.
The goal here is that the root page never changes. When you navigate, you are actually navigating inside the frame that itself is inside the root page. As a result, you can put things in the root page, like an appbar. This appbar would be shared across all pages that are loaded in the root page's frame.
It's a clever implementation. But there is a caveat. If any of your pages need to have a custom appbar themselves, you would need to write quite a bit of special code to inject the page's appbar into the shared appbar. If you don't have this "custom" requirement, then this is a simple and effective solution.
Option 2
There no reason you can't create a UserControl that implements an AppBar or CommandBar and simply include that in the pages you what to have shared logic. That's probably the way I would do it if there were any chance of a custom appbar in my pages.
Best of luck!

Each Page in a Windows Store app using C++, C#, or Visual Basic can have an AppBar assigned to its TopAppBar and BottomAppBar properties. But you might want to use the same AppBar across related pages in your app to provide common navigation or commands.
Here is a Tutorial How to share an app bar across pages

You can put your AppBar code into App.xaml and correspondence code behind into App.xaml.cs and then include that AppBar by its name in the number of pages where you want it like..
<phone:PhoneApplicationPage
x:Class="PhoneApp1.myPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
.
.
.
.
ApplicationBar="{StaticResource myGlobalAppBar}" >
where "myGlobalAppBar" is the name of AppBar given in the App.xaml file.

Related

Universal Windows App layout page

I'm starting a new universal windows app project. Normally I do web developer but have been asked to do a Universal Windows Application.
I'm starting to get somewhere now and have been using MVVM Light and have a couple of views set up.
Anyway here is my question, is there a way for me to have a "Layout" page, similar to what I would have it ASP.NET MVC?
For example, I have the main xaml page in my app, and the root control in that page is a SplitView. I have it so that when I click a button in the split view pane it takes me to the correct xaml view for that button. The thing is this page doesn't have the split view so I no longer have any navigation.
Surely I don't need to duplicate my menu across every view? I assume I'm missing something blindingly obvious.
Thanks,
The Splitview works this way that the page containing the split view will always be active (I normally call this page shell.xaml)
In here you can place your hamburger menu and add other things that should be visible all the time. Then you create a frame inside the splitview where your child pages live. handling navigation should only navigate using this frame and not the main page.
Here is a working sample that might explain this better:
https://code.msdn.microsoft.com/Sample-splitview-with-edcc2ca9
I think you need something like this.
You have to navigate your pages just to frame in SplitView content, not to default application's frame.
<SplitView>
<SplitView.Pane>
Your menu
</SplitView.Pane>
<SplitView.Content>
<Frame Name="ContentFrame" />
</SplitView.Content>
</SplitView>
And than in code-behind set the page you want like default
public MainPage()
{
this.InitializeComponent();
ContentFrame.Navigate(typeof(Homepage));
}

Scoped navigation service in Prism UWP

I am using Prism 6 for UWP and Unity.
Scenario:
I have a login page, and some other selection pages before I navigate to a Menu page that hosts a SplitView control. I want the navigation from this point to only target the content area of the SplitView control, but because my INavigationService was created in the context of the initial Frame I cannot do this.
I have seen the SplitView example but that basically sets the SplitView UI as the top Window.Current.Content right off the bat. This is why I am seeing the current behavior. I cannot simply take the initial Frame and set is to the SplitView Content area.
What is a good way to have my navigation now target the SplitView Content area?
- Recreating a navigation service? Don't know how I would inject this in the correct pages.

How to add same control to every screen?

Making first windows store app and need to have some controls show up at the top and bottom of every screen. When I did some WPF dev, I created a usercontrol and added it to every page. How is this done in windows store apps?
More specifically the header has a company logo and a status icon that changes based on an external resource (idle -> running, etc). The footer is where navigation happens in a somewhat linear fashion. Also, the footer displays the date and current time that continues to update. with the content in the middle changing based on what is selected in the footer.
There are a couple of different ways to do this. It really matters on whether you need it to be the same control (same instance) or if it is just a header/footer control which is added to each page and changes based on what you put into it.
Firstly, if this is something that can be incorporated into a CommandBar, that's the first thing I suggest you try. Then you can just create a StaticResource for each CommandBar, styled in the way you want for the header and footer. When you declare each page, in the root declaration, just set:
Page.TopAppBar="{StaticResource MyHeader}"
Page.BottomAppBar="{StaticResource MyFooter}"
You can make them Sticky and style them in any way that you would prefer, including having a collapsed version with just an ellipsis (...) to hide/show it. You can store all of the data for them inside of their own ViewModels, and have the control's DataContext just bind directly to the VM so that each instantiation pulls from the same data.
If it's not something that can be incorporated into a type of CommandBar, then I suggest you create your own Page subclass. The Template for it will wrap its ContentPresenter in your custom Header and Footer objects, likely in a Grid panel. This way will create a new copy of them each time, so they'll still need to bind to a ViewModel.
The final option that I see is to create a parent Page which has, similar to the subclass method, your header and footer wrapping the content. This time though, have them wrap a Frame. Then, all you have to do is call Frame.Navigate on that Frameand the header/footer controls will not be recreated, only the content in between them.
You can see something similar to this done in most of the Windows 8/8.1 app samples. They create a Content Frame, then navigate that through each page of the sample, generally on a selection from a navigation ListBox.
If you add a bit more information, I can try and tailor the answer a bit and provide some more specificity, but these are the general ways that I can see for you to accomplish what you have described.
Update:
Based on what you've said, to me it seems like the easiest thing to do would be to go with the third option, a Page wrapping a Frame. I suggest this because then it makes it quite easy for the bottom bar to affect navigation, and it sounds like you don't want the header or footer to be affected by page transitions.
If you check out the official ListView sample, you'll note their main page is declared something like this:
<Page
...>
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<!-- Navigation and other stuff -->
<Frame Grid.Column="1" x:Name="ScenarioFrame" Margin="30,50,30,0" />
</Grid>
</Page>
This is your basic main page declaration. You can then declare three Rows, one for your header, one for your Content, and one for your footer. If you want the footer to pop in and out, you can totally build the footer you have described into a CommandBar and include it on this page. Whenever you need to Navigate, just call ScenarioFrame.Navigate from your code-behind. You can now create Pages like normal, and Navigate to them like you would any other app.
This should also be 'Universal', so you should be able to include it in a Universal app, so long as you make sure your footer scales to the size of the screen (which you should already do). If you do try this, make sure that your navigation code in your main page is as generic as possible and the majority of the 'specialty navigation', such as Panes and settings are handled each platform-specific page, or at least via messaging (such as that provided by MvvmLight) and a NavigationHelper class.
Hope this helps and happy coding!

How can I create an AppBar in Metro that works in a WebView?

So I got a normal AppBar to work in a C# metro app, but the problem is I need the app to display an html page. I create a WebView that takes up 100% of the width and height of the page, and by doing so, the AppBar doesn't show up anymore on right clicks and edge swipes. Is there a way for the AppBar to work with such a WebView in place?
--Resolved--
What I ended up doing was adding a 1px border around the WebView so that swipes could be detected. Since what I included in my WebView dynamically changes with time, WebViewBrush didn't work out for me. Instead I just shrunk the size of the WebView when the AppBar is opened and then expanded it when it was closed.
Not trying to steal Filip's answer, but I think a few more details are necessary to fully answer the question.
Even with a WebView running full-screen, the AppBar tries to show itself when you right-click or swipe. You can prove this by subscribing to the AppBar.Opened event. What's interesting is that the AppBar appears to somehow know it's obscured and automatically closes itself. Even if it didn't close itself, you wouldn't be able to see it because it's obscured under the WebView.
Filip had the right idea about hiding the WebView and using WebViewBrush while the AppBar is open. You can find a good example of doing that here:
http://msdn.microsoft.com/en-us/library/windows/apps/windows.ui.xaml.controls.webviewbrush.aspx
As for when to swap between WebView and WebViewBrush, I'd simply do it on AppBar.Opened and reverse it on AppBar.Closed. AppBar is light dismiss, meaning as soon as you tap anywhere outside of it's client area it will close.
One last word of advice: In my testing it seemed that the swipe gesture was getting swallowed sometimes. That problem seemed to go away when I put a 1 pixel boarder on top and bottom of the WebView. Your mileage may vary.
You need to hide the WebView while displaying XAML UI on top of it and use the WebViewBrush instead.
As suggested above, the 1px border can help with ensuring the top/bottom swipe is honored for the AppBar. However, similar to #matthieu I was still having issues getting the AppBar to open reliably when using the mouse and right-click method.
The issue was that I included the XAML element as a peer to the WebView, rather than as a parent as the MSDN reference for AppBar.Closed suggests:
<Border BorderBrush="Gray" BorderThickness="2" Margin="100,20,100,20">
<Grid>
<WebView x:Name="contentView" Source="http://www.contoso.com"/>
<Rectangle x:Name="contentViewRect"/>
</Grid>
</Border>
If I apply the border this way, the AppBar also reliably opens with the mouse.
One last thing to note is that using a BorderBrush="Transparent" works fine as well, so you don't have to actually see the ugly border. My final XAML was something like:
<Border BorderThickness="0,1,0,1" BorderBrush="Transparent">
<Grid>
<WebView x:Name="WebView"></WebView>
<Rectangle x:Name="RectWebViewBrush"></Rectangle>
</Grid>
</Border>

How to get current displayed page object during navigation form one page to other?

i have made an application where MainPage is the opening window of my application.
Then i added two pages to the project. One is portrait and other is of landscape mode.
Now there is a controller class which will be controlling the main working of the application. Now i want that when i navigate from main page to portrait or landscape page then i will able to get the object of the current opening page which i require in controller class.
Is there any work around ?
There is no way to get the details of the page that was last opened automatically. You will have to do this yourself.
There are 2 common approaches to this:
Use a global variable to store that last viewed page.
Use a messaging system to inform the MainPage which page was displayed last.