Jul 022011
 

Make sure to read part 1 first!

WP7Contrib offers numerous transitions, these include:

Continuum
The selected item in a list will animate out, and the next page will have the heading animate in. The reverse happens on returning to the original page. This is a great effect if the user is selecting a specific item to view more detail.

Rotate
The page rotates in/out. A bit ostentatious for my tastes.

Slide
There are various slide animations offered, these mimic the kinds of transitions you get with iOS. SlideUp and SlideDown are ideal for popups.

Turnstile
The default transition we all know and love

Turnstile Feather
My personal favourite, and one we’ll see a lot more of in Part 3. This is the same as Turnstile, except it will animate out each element in a list from top to bottom. This is the same effect you see on the phone home screen when you select an app to launch.

If you want to see all of the transitions on offer, download the WP7Contrib source code and open the ‘PageTransitions’ solution within the ‘Spikes’ folder. This provides a demo of all of the transitions on offer within WP7Contrib.

Let’s Play

Let’s try the Turnstile Feather and Continuum transitions out. You’ll need a project with a screen that’s a ListBox, if you don’t have one, download the demo app from the first part of this series. If you want to see the demo right now, click here to download the demo app for part 2.

Go into the code-behind for the page with the ListBox and add the following override:

protected override AnimatorHelperBase GetAnimation(AnimationType animationType, Uri toOrFrom)
{
    return base.GetAnimation(animationType, toOrFrom);
}

This is an extremely powerful override that allows you to fully customise the kind of animation used when the page is navigated to or from. The first parameter is the type of animation you need to return. The second parameter is the uri for the page that the user is either navigating to, or navigating from. If ever you’re not sure, use the base implementation which will almost always provide a Turnstile animation. The Turnstile animation is a good fall-back animation, so it’s often wise to handle specific cases yourself, and let the base implementation handle the rest.

Now you could run the app right now and it’ll work, but we want to trigger a Continuum transition on the way out, and a Turnstile Feather animation on the way back in. To do this, we need to tell which animations we want WP7Contrib to use:

protected override AnimatorHelperBase GetAnimation(AnimationType animationType, Uri toOrFrom)
{
    switch (animationType)
    {
        case AnimationType.NavigateForwardOut:
        case AnimationType.NavigateBackwardOut:
            return this.GetContinuumAnimation(TheListBox, animationType);

        case AnimationType.NavigateBackwardIn:
            return new TurnstileFeatherBackwardInAnimator()
            {
                ListBox = TheListBox,
                RootElement = LayoutRoot
            };

        case AnimationType.NavigateForwardIn:
            return new TurnstileFeatherForwardInAnimator()
            {
                ListBox = TheListBox,
                RootElement = LayoutRoot
            };
    }

    return base.GetAnimation(animationType, toOrFrom);
}

Notice we let WP7Contrib handle any animations we don’t explicitly handle ourselves. This ensures if the app is extended in the future the user experience isn’t unduly affected.

The Continuum animation has three properties, a StoryBoard, RootElement and LayoutRoot. This allows you to customise the animation applied to the selected element, however most of the time the default animation is the correct one. For this reason we get WP7Contrib to create the animation for us by calling GetContinuumAnimation.

The Turnstile Feather animation requires the ListBox you wish to animate and the RootElement. The RootElement in this case is the same element you set as the AnimationContext. You could set a different RootElement if required, but it’s unlikely you’ll ever need to do this.

Now run your app and admire your handy work! You can download a fully functional demo project here.

Want yet more? Click here for part 3.

Jul 022011
 

WP7Contrib offers an alternative to the WP7 Silverlight Toolkit transitions, and in my humble opinion, the alternative is significantly better in this case. The Silverlight toolkit offers easy integration of transitions via a little XAML markup and a minor change to the root frame. The biggest problem with the toolkit transitions are that they’re slow and exceedingly memory intensive with complex layouts consuming copious amounts of memory. In my latest app the transitions alone could use up to 40MB. Don’t forget, there is a 90MB limit for all apps when operating on devices with 256MB RAM.

WP7Contrib offers an alternative that’s code-based rather than markup-based. This may be preferable, or it may not depending on your internal setup. Personally for something like transitions I prefer code-based so transitions are the ‘default’ rather than the exception.

The greatest thing about WP7Contrib Transitions, is that they’re a doddle to implement if you just want to have transitions between pages. In WP7 the ‘standard’ transition is the turnstile transition – this is where each screen appears and disappears as if they’re pages in a book. Here’s how to get this transition into your app:

Simple Transitions

If you want to see the transitions for yourself, click here to download the demo app. Otherwise , download WP7Contrib and compile it. Once you’ve done this, add the WP7Contrib.View.Controls and WP7Contrib.View.Transitions assemblies to your project References. These are the only two assemblies required to get transitions working, and I prefer to include as few assemblies as possible to keep load times fast.

Next you need to make some minor tweaks to every page you want to animate. Add the following namespace to the XAML file:

xmlns:animation="clr-namespace:WP7Contrib.View.Transitions.Animation;assembly=WP7Contrib.View.Transitions"

Next change the page type to ‘animation:AnimatedBasePage’. To do this the first line of your XAML file should be:

<animation:AnimatedBasePage

And the last line should be:

</animation:AnimatedBasePage>

Now go into the code-behind and change the base type of your page to ‘AnimatedBasePage’. The final change is to add the following line into the constructor:

AnimationContext = LayoutRoot;

This tells WP7Contrib that your ‘root element’ is ‘LayoutRoot’. You can set any element to be the AnimationContext, this is useful if you want to only animate a sub-area of the page between pages. Generally speaking you’ll want to target LayoutRoot, or whichever element you’ve got containing all of your UI. This is the big difference between WP7Contrib and the WP7 Toolkit which targets the page frame itself.

Compile and run your app – you should find your pages automatically use the turnstile transition. Don’t forget you can download the demo app here.

Personally, I can’t recommend WP7Contrib transitions enough. They have a few caveats, but the performance improvements and memory savings are substantial. I hope that this article has given you a taster of the transitions and how easy they are to implement.

Hungry for more? Click here to view part 2 where we cover additional transitions.

Jun 072011
 

I quite like to have a global Performance Progress Bar in my Windows Phone 7 apps so the user has a consistent frame of reference when I’m interacting with web services. The requirements are simple, a progress bar that appears on all pages without any special requirements (ie. no custom controls, special code snippets, etc.). It should be managed in one place, and be easy to extend. Fortunately the extreme flexibility Silverlight offers makes this a doddle:

First add the following style to your App.xaml file:

<Style x:Key="mainFrameStyle" TargetType="phone:PhoneApplicationFrame">
    <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>
                        <toolkit:PerformanceProgressBar
                            IsIndeterminate="True"
                            VerticalAlignment="Top"
                            Canvas.ZIndex="999"
                            Foreground="{StaticResource PhoneAccentBrush}"
                            Visibility="Collapsed"
                            Loaded="globalProgressBar_Loaded"
                            />
                        <layout:ContentControl
                                ContentTemplate="{TemplateBinding ContentTemplate}"
                                Content="{TemplateBinding Content}"
                                HorizontalAlignment="{TemplateBinding HorizontalAlignment}"
                                HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
                                VerticalAlignment="{TemplateBinding VerticalAlignment}"
                                VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
                                Margin="{TemplateBinding Padding}">
                        </layout:ContentControl>
                    </Grid>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

Next go into the code behind, and add the following variable to the top of the class:

private PerformanceProgressBar _globalProgressBar = null;

Next add the following methods to the bottom the App class:

private void globalProgressBar_Loaded(object sender, RoutedEventArgs e)
{
    _globalProgressBar = sender as PerformanceProgressBar;
}

public void ShowProgressBar()
{
    if (_globalProgressBar != null)
        _globalProgressBar.Visibility = Visibility.Visible;
}

public void HideProgressBar()
{
    if (_globalProgressBar != null)
        _globalProgressBar.Visibility = Visibility.Collapsed;
}

Now find the InitializePhoneApplication() method, and amend the RootFrame instantiation code to the following:

RootFrame = new PhoneApplicationFrame()
{
    Style = (Style)Resources["mainFrameStyle"]
};

And you’re done! You can call the progress bar like so:

((App)App.Current).ShowProgressBar();
((App)App.Current).HideProgressBar();

You can download the sample project here for your reference.

Update: This method for displaying a global ProgressBar doesn’t always play well with the WP7 Toolkit Transitions. However, I would highly recommend using the WP7Contrib Transitions anyway (they work well with the global ProgressBar too). I’ve created a 3-part guide on the transitions here.

Jun 042011
 

It’s quite common to have a ‘More’ button at the end of long lists within a LongListSelector. The problem is the template inexplicably doesn’t cascade the DataContext, so you have no access to the collection to trigger a more command. Fortunately the workaround is simple, albeit you can’t use pre-defined DataTemplates.

<toolkit:LongListSelector x:Name="SimilarList" ItemTemplate="{StaticResource GeneralCatalogListItemTemplate}" SelectionChanged="SimilarList_SelectionChanged" DataContext="{StaticResource dummyCatalogTitlesList}" ItemsSource="{Binding}" IsFlatList="True">
    <toolkit:LongListSelector.ListFooterTemplate>
        <DataTemplate>
            <bindings:CommandButton Content="More..." Command="{StaticResource moreCommand}" DataContext="{Binding ElementName=SimilarList, Path=DataContext}" CommandParameter="{Binding}" />
        </DataTemplate>
    </toolkit:LongListSelector.ListFooterTemplate>
</toolkit:LongListSelector>

You need to give your list a name, then when setting the DataContext for your controls make sure to provide the ElementName as seen above.

I’m not sure why the other templates cascade correctly and this one doesn’t, but I’m hopeful it’ll be fixed in a future release of the toolkit. As an aside there is a fairly clean workaround if/when MS add the Freezable class to WP7.

May 302011
 

So you’re getting the most awful error Silverlight can throw… I really wish I could tell you that if you hope on one leg while reciting the alphabet in reverse order will give you a vaguely helpful error message, but I can’t. The most common causes are:

Basically if there’s anything Silverlight doesn’t like at runtime, it’ll tend to throw this error. I’ll try to help you with the last two on the list above.

Layout Issue

In the stack trace for the error, check for the tell tale references to ‘MeasureOverride’. This means you’ve probably got a layout issue. What you’ve likely got is a fixed-width element, and the children require more space than you’re providing. In my case I had a table column that was 2 pixels too narrow. If your layout allows it, try to avoid using pixel sizes even if you know the correct size since sometimes additional styling can change required sizes slightly.

Some other problem

This one is the trickiest to solve, for obvious reasons. The best way I’ve found to debug is to go completely old school and strip everything back to the bare minimum and see if your code works then. This includes removing data binding. You need to get the page to display without any errors. Once you’ve reached this point slowly start re-introducing code. Eventually the error will re-appear and you should have a much better idea of exactly where the problem is. Of course you have to solve the problem still, but at least you know roughly where it is now.

May 292011
 

Recently I had a problem with Isolated Storage Settings on WP7 – the entire collection appeared to be wiped every single time I restarted the app. The problem turned out to be the deserialization stage of IsolatedStorageSettings, in essence if any object can’t be re-instantiated, then the entire collection is inaccessible. The collection will work correctly until you attempt to retrieve something that can’t be instantiated.

At the bare minimum the constructor of your class must be public.

All non-public properties will also fail to be restored, resulting in a rather empty object instance when you come to load the values that should have been saved (and have been… they just don’t come back). Be very careful with this issue, you may not notice the problem until it’s too late.

May 212011
 

While developing a Silverlight WP7 app, it’s often handy to display demo content in design view so you have an idea of how real content will look. This is one of the biggest advantages of the MVVM architecture – separate data for design and runtime, as demonstrated below:

Fortunately Alex Pendleton has created a Lorem Ipsum generator in .NET 2.0 called NLipsum. Unfortunately it doesn’t work directly on WP7 without a little massaging. Fear not, for I have done the work for you! You can download the project files here, or the binary here.

The dll contains some raw XML files for generating the lipsums, and these are loaded at runtime. For this reason it’s best not to have the binary included with release builds of your app, lest you get a slower startup and increased memory usage. I’ve put in some caching that should mean you can call the generator as much as you like without worrying too much about performance. To use the generator, include it into your project and import the namespace:

using NLipsum.Core;

Then, it’s a simple case of calling the generator to do your bidding:

return LipsumGenerator.Generate(1, Features.Paragraphs, null, Lipsums.LoremIpsum);

return LipsumGenerator.Generate(1, Features.Sentences, null, Lipsums.TheRaven);

return LipsumGenerator.Generate(2, Features.Words, null, Lipsums.LeMasque);

If the content doesn’t show in design view, try re-building your app. This will refresh your design-time databinding as well as bringing in any changes you’ve made to the model (such as adding the lorem ipsum).

May 192011
 

At some point you’re probably going to need to have the height of a WebBrowser on your Windows Phone app resize automatically to fit the content, so that the other content on the page can wrap nicely around it. Fortunately MS have provided all of the functionality you need to pull this off, albeit in a somewhat roundabout way.

Adding the browser

First of all put a WebBrowser in to your XAML file, or alternatively add it pragmatically. Make sure IsScriptEnabled is set to true, by default it’s false.

If you’re adding the browser in code, make sure the height is at least 1 pixel.

Hooking up events

You’ll need to hook up the ‘ScriptNotify’ event, use the following code in the event handler:

protected void WebBrowser_ScriptNotify(object sender, NotifyEventArgs e)
{
	WebBrowser thisBrowser = (WebBrowser)sender;
	int height = Convert.ToInt32(e.Value);
	double newHeight = height * 1.5;

	thisBrowser.Height = newHeight;
}

This gets the browser that fired the event (so feel free to re-use the event for multiple browsers), gets the height the browser thinks it needs to display the content. The height value is actually set by the JavaScript, so due to the built-in scaling of the content you’ll need to multiply it by 1.5. Finally the browser’s height is set to the correct value to fit the content.

Add a teaspoon of JavaScript

Lastly, you need to add some JavaScript to the HTML you pass into the browser:

<script type="text/javascript">
    window.onload = function () {
        var elem = document.getElementById('content');
        window.external.Notify(elem.scrollHeight + '');
    }
</script>

This code will find an element with the ID of ‘content’, and send the height to your program. This means you’ll need to wrap all of your content in a div like so:

<div id="content">
    <p>Hello World</p>
</div>

You may be wondering why we don’t just get the scrollHeight of body. While experimenting I found this was the most reliable – but if body works for you then it is the more elegant solution. You may also be wondering why we add ” to the scrollHeight in the JavaScript. This is due to window.external.Notify only supporting text strings, however the height is a number. By adding ” we convert the number to a string meaning window.external.Notify will work as intented. If you ever find Notify not working – check the datatype, it fails silently.

Finishing up

This should be enough for you to get started. You’ll probably want to customise the CSS to match the phone’s current theme, but that’s another guide for another day. One tweak you should probably think about doing now is to add some padding to the content div, otherwise the HTML you output tends to look out of place rammed right up against the border of the WebBrowser.

If you find the height returned isn’t correct, it’s most likely due to the scaling of the web content. Set the viewport width to a fixed value (you can pass in the width of the WebBrowser if generating the HTML on the fly, or you have the ability to process it before the browser reads in the HTML). You may also need to set the width of the div as well, using the aforementioned method.

Setting the viewport:

<meta name="viewport" content="width=320" />

Setting the div width + padding:

<style type="text/css">#content { padding: 10px; width: 300px; }</style>