Visually Located

XAML and GIS

Pluralsight subscription give away

Congratulations to Mohana Rao Ramasetty and Mils†ein® for winning a free one month subscription to pluralsight!


I have two one month subscriptions to Pluralsight that I will give away to two lucky people at the end of the week. These are two one month subscriptions that I have won, but will not use as I already have an account. I have confirmed with Pluralsight that the codes are valid.

image

All you have to do is tweet

I want a free one month subscription to @pluralsight from @skendrot

Rules:

  1. Tweet the above
  2. You do not need to follow me. In fact, you can unfollow me if you so choose.
  3. More tweets != more chances to win.
  4. Contest ends midnight 1 Mar EST.

Add a persistent element to every page of your phone apps

Adding ad controls to apps is a pretty common thing. Some apps have ads on every page of the app. Some apps only have ads on some pages. When you want to have ads on one page you have to manually add the control to each page. Wouldn’t it be cool to only add it once and it shows up on all of your pages? This is exactly what someone recently asked on Stack Overflow. This is possible to do and quite simple. First, add a new style to your App.xaml resources and name it AdPhoneApplicationFrameStyle.

<Style x:Key="AdPhoneApplicationFrameStyle" TargetType="toolkit:TransitionFrame">
    <Setter Property="IsTabStop" Value="False"/>
    <Setter Property="Foreground" Value="{StaticResource PhoneForegroundBrush}"/>
    <Setter Property="FontSize" Value="{StaticResource PhoneFontSizeNormal}"/>
    <Setter Property="FontFamily" Value="{StaticResource PhoneFontFamilyNormal}"/>
    <Setter Property="HorizontalAlignment" Value="Stretch"/>
    <Setter Property="VerticalAlignment" Value="Stretch"/>
    <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
    <Setter Property="VerticalContentAlignment" Value="Stretch"/>
    <Setter Property="Background" Value="Transparent"/>
    <Setter Property="BorderThickness" Value="0"/>
    <Setter Property="BorderBrush" Value="{x:Null}"/>
    <Setter Property="Padding" Value="0"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="phone:PhoneApplicationFrame">
                <Border x:Name="ClientArea" BorderBrush="{TemplateBinding BorderBrush}" 
                        BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" 
                        HorizontalAlignment="{TemplateBinding HorizontalAlignment}" VerticalAlignment="{TemplateBinding VerticalAlignment}">
                    <Grid>
                        <Grid.RowDefinitions>
                            <RowDefinition Height="*"/>
                            <RowDefinition Height="Auto"/>
                        </Grid.RowDefinitions>
                        <ContentPresenter ContentTemplate="{TemplateBinding ContentTemplate}" 
                                          Content="{TemplateBinding Content}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" 
                                          Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
                        <Rectangle Height="80" Width="480" Fill="Red" Grid.Row="1"/>
                    </Grid>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

In the style I’ve added a new Rectangle to simulate our AdControl. The Rectangle has been placed inside a Grid in the second row which is oriented to the bottom. Next in the App.xaml.cs within the InitializePhoneApplication method, set the style on RootFrame object.

private void InitializePhoneApplication()
{   
    ...
 
    RootFrame = new TransitionFrame();
    RootFrame.Style = (Style)Resources["AdPhoneApplicationFrameStyle"];
 
    ...
}

Now you always have that element for every page of your app!

That’s pretty cool, but what about doing page transitions? Hopefully you are putting page transitions into your app. This is still possible, but we need to change the style of the Frame to match the Frame being used. If you are using the Windows Phone Toolkit TransitionFrame, your style would change to the following.

<Style x:Key="AdTransitionFrameStyle" TargetType="toolkit:TransitionFrame">
    <Setter Property="Background" Value="{StaticResource PhoneBackgroundBrush}"/>
    <Setter Property="BorderBrush" Value="Transparent"/>
    <Setter Property="BorderThickness" Value="0"/>
    <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
    <Setter Property="VerticalContentAlignment" Value="Stretch"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="toolkit:TransitionFrame">
                <Border x:Name="ClientArea" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" 
                        Background="{TemplateBinding Background}" Margin="{TemplateBinding Margin}">
                    <Grid>
                        <Grid.RowDefinitions>
                            <RowDefinition Height="*"/>
                            <RowDefinition Height="Auto"/>
                        </Grid.RowDefinitions>
                        <ContentPresenter x:Name="FirstContentPresenter" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" 
                                          VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
                        <ContentPresenter x:Name="SecondContentPresenter" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" 
                                          VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
                        <Rectangle Height="80" Width="480" Fill="Red" Grid.Row="1"/>
                    </Grid>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

This style uses the same approach to add the Rectangle by adding it to a second row in the grid. When using the WP Toolkit TransitionFrame, you need to change the code within the InitializePhoneApplication method to create a TransitionFrame rather than a PhoneApplicationFrame.

private void InitializePhoneApplication()
{
    ...
 
    RootFrame = new TransitionFrame();
    RootFrame.Style = (Style)Resources["AdTransitionFrameStyle"];
 
    ...
}

Now we have our persistent element and our page navigation; the best of both worlds!

Asynchronous Predicates, Actions and Funcs

I love the built in Predicate, Action, and Func delegates. They provide simple ways for methods to be passed to other objects. Suppose you had an interface that processes some results. In the Process method, it has a parameter that specifies if a given item is valid and ready for processing

public interface IProcessResults
{
    IEnumerable<IProcessedItem> Process(IEnumerable<IItem> items, Predicate<IItem> isValid = null);
}

If the predicate existed, the implementing class would call that method to determine if an item is valid or not. This is all well and good, but we live in async world now. Windows Store APIs enforce async everywhere they can. Windows Phone and the .Net APIs are not quite there, but do provide everything needed so that you may be able to make your app Fast and Fluid. Why should we be held back by these synchronous delegate methods?

Let’s see if we can take the existing APIs, and make them asynchronous. First we have to define our predicate.

Predicate<IItem> shouldProcess;

Maybe we want to prompt the user with a MessageDialog asking them if they want to process the item.

Predicate<IItem> shouldProcess = item =>
{
    MessageDialog dialog = new MessageDialog("Do you want to process the item: " + item.Title);
    dialog.Commands.Add(new UICommand("yes"));
    dialog.Commands.Add(new UICommand("no"));
    var result = await dialog.ShowAsync();
    return result.Label == "yes";
};

We cannot call await on the ShowAsync method, because our Predicate is not marked async. We can attempt to make our method async, by adding the keyword.

Predicate<IItem> shouldProcess = async item =>
{
    MessageDialog dialog = new MessageDialog("Do you want to process the item: " + item.Title);
    dialog.Commands.Add(new UICommand("yes"));
    dialog.Commands.Add(new UICommand("no"));
    var result = await dialog.ShowAsync();
    return result.Label == "yes";
};

But then we get the error

The return type of an async method must be void, Task, or Task<T>

Using Resharper, I can hit Alt-Enter and change the Predicate to Func<IItem, Task<bool>>

Func<IItem, Task<bool>> shouldProcess = async item =>
{
    MessageDialog dialog = new MessageDialog("Do you want to process the item: " + item.Title);
    dialog.Commands.Add(new UICommand("yes"));
    dialog.Commands.Add(new UICommand("no"));
    var result = await dialog.ShowAsync();
    return result.Label == "yes";
};

Goodness, that looks horrible! I wanted a simple Predicate and I ended up with Func<IItem, Task<bool>>. Our interface would need to change the method signature to the following:

public interface IProcessResults
{
    Task<IEnumerable<IProcessedItem>> Process(IEnumerable<IItem> items, Func<IItem, Task<bool>> shouldProcess = null);
}

We can make this better by creating our own delegate.

public delegate Task<bool> AsyncPredicate<in T>(T obj);

I choose to go with AsyncPredicate rather than PredicateAsync because PredicateAsync sounds weird. With this change, we can modify our interface as such

public interface IProcessResults
{
    Task<IEnumerable<IProcessedItem>> Process(IEnumerable<IItem> items, AsyncPredicate<IItem> shouldProcess = null);
}
And the creation of our predicate turns into
AsyncPredicate<IItem> shouldProcess = async item =>
{
    MessageDialog dialog = new MessageDialog("Do you want to process the item: " + item.Title);
    dialog.Commands.Add(new UICommand("yes"));
    dialog.Commands.Add(new UICommand("no"));
    var result = await dialog.ShowAsync();
    return result.Label == "yes";
};

In my mind this looks and reads much better. Now that we have one delegate, we can start creating more, and more.

public delegate Task<bool> AsyncPredicate<in T>(T obj);
public delegate Task AsyncAction();

Place your app title in the System Tray

I’ve been using the new Bing apps a lot and I really like how the app name is in the SystemTray.

wp_ss_20140211_0001

This looks awesome and frees up valuable space for your app! I have found that sometimes I remove the app title from pages to allow for more content. Accomplishing this for your apps is soooo simple! All you need to do is comment out the TextBlock that you are using for your title, and add the following bit of xaml to your page (outside of any grids and such)

<shell:SystemTray.ProgressIndicator>
    <shell:ProgressIndicator Text="My Application" IsVisible="True" IsIndeterminate="False"/>
</shell:SystemTray.ProgressIndicator>

Make sure you have set the SystemTray to be visible by setting the IsVisible property to true. You still get the advantage of the text going away when the user taps the tray.

If you do this, you will need to rethink how you show that the app is loading. The ProgressIndicator is suppose to be used to show that stuff is happening and that the user should keep calm, and wait. You have a few options for showing loading status.

Continue to use the SystemTray ProgressIndicator

You can continue to use the ProgreessIndicator within the SystemTray if you so wish. You will need to change the IsIndeterminate property and probably the Text Property.

// Make sure to give the ProgressIndicator a name
Indicator.Text = "Loading";
Indicator.IsIndeterminate = true;

The nice thing about the ProgressIndicator is that the properties are DependencyProperties. This means that they accept binding and can be set from a ViewModel.

<shell:SystemTray.ProgressIndicator>
    <shell:ProgressIndicator Text="{Binding IndicatorText}" IsVisible="True" IsIndeterminate="{Binding IsLoading}"/>
</shell:SystemTray.ProgressIndicator>

With either approach make sure that you set the Text and IsIndeterminate back when loading is done.

Use the ProgressBar

The ProgressBar is a very handy control already built into the ecosystem. It is very similar to the the ProgressIndicator in the SystemTray. The ProgressBar is an actual Control, this means you set the Visibility property instead of the IsVisible property. If you are binding, you will need a BooleanToVisibilityValueConverter. It still has an IsIndeterminate property to specify if you should see the dots flying across the screen or a solid line showing how much progress has been made. This is what the Bing apps use. When using this control in apps, make sure not to allocate space for it. What I mean by this is put it in a Grid in the same row as your page title, or other content. If you specify a row for it, or put it in a StackPanel, your page content will jump when the ProbressBar is shown or hidden.

Here is a xaml snippet of it being used.

<Grid x:Name="LayoutRoot" Background="Transparent">
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="*"/>
    </Grid.RowDefinitions>
    
    <!--TitlePanel contains the name of the application and page title-->
    <StackPanel Grid.Row="0" Margin="12,17,0,28">
        <!--<TextBlock Text="MY APPLICATION" Style="{StaticResource PhoneTextNormalStyle}"/>-->
        <TextBlock Text="page name" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
    </StackPanel>
 
    <ProgressBar Grid.Row="0" VerticalAlignment="Top" Foreground="White" 
                 IsIndeterminate="{Binding Loading}" 
                 Visibility="{Binding IsLoading, Converter={StaticResource BoolToVisConverter}}" />

Notice the progress dots below.

progressbar

Use a third party control such as Telerik’s RadBusyIndicator

The RadBusyIndicator from Telerik is a nice control that has many default style options. This control allows you to restyle to whatever you want. I use this control for my main loading screen in Disney Expedition. Much like the IsVisible property of the ProgressIndicator, the RadBusyIndicator has an IsRunning boolean property to specify if it should be visible or not. You can change between 9 preconfigured animations by setting the AnimationStyle property.

<telerikPrimitives:RadBusyIndicator IsRunning="True" AnimationStyle="AnimationStyle1" Grid.RowSpan="2" Background="CC000000"/>

This control will take up as much space as it is given and have a background that covers all of the content on your page. If you want to create your own style, you can set the IndicatorAnimationStyle.

 

Putting your app title in the SystemTray really helps you show more content in your apps and let’s you continue to brand your app with your title.