Sometimes you need a progress bar (or any other control) on potentially all pages in your windows phone application. In these cases, you can use the root frame template to specify the progress bar on your main XAML and give access to it through the application object. This way, your pages can share the same progress bar. It’s actually pretty simple to do. Three steps:
1. Define your template for the root frame.
2. Once loaded, get a ref to the progress bar
3. Extra credit: Create an “addref/release” mechanism for showing/hiding the progress bar.
Step 1: Template
Define your template resource – easiest way to do this is in the app’s resources:
<Application.Resources>
<ControlTemplate x:Key=”TopLevelTemplate” TargetType=”phone:PhoneApplicationFrame”>
<Grid x:Name=”GlobalContainer”>
<Grid Grid.Row=”0″ x:Name=”ClientArea” >
<ContentPresenter />
<ProgressBar IsIndeterminate=”True” HorizontalAlignment=”Stretch” VerticalAlignment=”Top” Loaded=”ProgressBar_Loaded” Visibility=”Collapsed”/>
</Grid>
</Grid>
</ControlTemplate>
</Application.Resources>
The <ContentPresenter> element is where the app will put your actual page. The <ProgressBar> element will create the shared progress bar control – in this case, we are placing it at the top of the page.
Next, in the code, make sure to assign the template to the root element:
public partial class App : Application
{
/// …
public App()
{
// …
RootFrame.Template = App.Current.Resources["TopLevelTemplate"] as ControlTemplate;
}
This will guarantee that the template is properly assigned.
Step 2: Gain access to the progress bar
The App does not have the same designer facilities as a windows phone page does and so assigning a Name to the control does not create the backing field for it (as it would on a phone page). And so, you need to gain access to it. One way of doing it is to hook the Loaded event (see above in the XAML) and in it, place the control in a field:
public partial class App : Application
{
private ProgressBar m_progressBar;
private void ProgressBar_Loaded(object sender, RoutedEventArgs e)
{
m_progressBar = (ProgressBar)sender;
}
}
Now that we have access to the progress bar, all you need to do to show/hide it is to use ((App)Application.Current).ProgressBar to show/hide it as needed.
Step 3: Extra credit
Since there are going to be multiple pages interacting with the control, it would be nice if it was self regulating (as to when to show and when to hide). A simple ref count mechanism can help here:And that’s about it – every time you do something that requires a progress bar, call ShowProgress(true). Otherwise, call ShowProgress(false).
public partial class App : Application
{
public void ShowProgress(bool show)
{
int d = show ? 1 : -1;
m_progressCount += d;
if (m_progressCount > 0)
{
m_progressBar.Visibility = Visibility.Visible;
}
else
{
m_progressBar.Visibility = Visibility.Collapsed;
}
}
}
Hope this helps.
http://cid-f5e0c616077a5eda.office.live.com/embedicon.aspx/BlogPublic/EverProgress.zip
Thanks this code just works!!!
Good post! I extended your ShowProgress method to also “dim” the content screen…
public void ShowProgress(bool show) { // Update progress bar count int d = show ? 1 : -1; _progressBarCount += d; if (_progressBarCount 0) { // Set root background rootFrame.Background = new SolidColorBrush(Colors.White); rootFrame.Opacity = 0.75; // Show progress bar _progressBar.Visibility = Visibility.Visible; } else if (_progressBarCount == 0) { // Set root background rootFrame.Background = new SolidColorBrush(Colors.White); rootFrame.Opacity = 1; // Hide progress bar _progressBar.Visibility = Visibility.Collapsed; } }My code got munched…let’s try that again.
public void ShowProgress(bool show)
{
// Update progress bar count
int d = show ? 1 : -1;
_progressBarCount += d;
if (_progressBarCount 0)
{
// Set root background
rootFrame.Background = new SolidColorBrush(Colors.White);
rootFrame.Opacity = 0.75;
// Show progress bar
_progressBar.Visibility = Visibility.Visible;
}
else if (_progressBarCount == 0)
{
// Set root background
rootFrame.Background = new SolidColorBrush(Colors.White);
rootFrame.Opacity = 1;
// Hide progress bar
_progressBar.Visibility = Visibility.Collapsed;
}
}
(Grrr….no preview, so I have no idea what the actual post will look like!)
Good post!
I extended your ShowProgress method to also “dim” the content screen. First we need to define the root frame…
And then set it’s opacity based on whether or not we are showing the progress bar…
if (m_progressCount > 0) { rootFrame.Opacity = 0.75; } else { rootFrame.Opacity = 1; }