PullToRefreshListView for UWP

Hello there developer who was just asked to incorporate the PullToRefresh behavior into one of your ListViews for the UWP app you are building. And of course you are looking to steal code on the internet. No blaming, I do it all the time. I actually want you to use this.

photo-15-642x322In case you just crawled out of your cave and aren’t really sure what PullToRefresh is here you go.

 

 

After evaluating the few solutions that were available on the internet I realized none of them fulfilled my requirements perfectly so I had to make my own. To be exact I had to steal code and was hoping that after some tweaking and refactoring I might be able to make it work.

After shamelessly stealing great code from  @dotMorten ‘s blog here RefreshBox for Windows Phone 7 as well as some interesting ideas from an otherwise mediocre Microsoft sample here XamlPullToRefresh I ended up with the code below.

Enjoy!

P.S Scroll to the bottom for some interesting details about this solution.

<Geeking>

The first most interesting and important detail of this solution is the trick the Microsoft sample used to bypass the classic problem of putting a ListView inside a ScollViewer which effectively kills Virtualization. Since the PullToRefresh indicator needs to be inside and above the ScrollViewer that hosts the list the same problem applies here. To overcome this
the Microsoft sample used two custom panels (an Inner and Outer) that know each other and can “talk” to each other. The reason virtualization is killed is because when a ListView is hosted inside a ScrollViewer then it thinks it has infinite vertical space because that’s what the ScrollViewer is telling it. The solution above works around this problem by allowing the Inner panel to figure out the Outer panel’s actual visible height and thus correctly calculate it’s own actual visible height which it can get by simply subtracting the size of the PullToRefresh indicator from the Outer panel’s height.
Cool trick.

The second most interesting and important detail was figuring out if the user released their finger when the ScrollViewer was over-stretched.  The limitation of the sample is that the Refresh is scheduled to be triggered once the user overstretches even if the user decides to cancel by slowly unstretching the ScrollViewer back to the original position.
The original attempts to solve this failed because ScrollViewer only exposes the DirectManipulationStarted and DirectManipulationCompleted events and the second one fires too late. Loong after the user has released their finger. The DirectManipulationPointerReleased  event was not available unfortunately.
The trick to solve this turned out to be the use of the ViewChanging event (see line 114) and figuring out the exact moment the user released his/her finger from the screen.
When this occurs at the desired time then :

  1. The event would be Inertial.
  2. The ScrollViewer would be overstretched so VerticalOffset should be zero and
  3. The direction of the inertial movement should be upwards towards the non-stretched state.

This allowed users to change their minds if they didn’t really want to refresh.

</Geeking>

Update: Microsoft has released an updated PullToRefresh  sample that you might also want to evaluate here.

Roots and magic behind C# Async/Await explained simply

Are you using C#’s new async/await feature?
It is cool right?
You learned how to use it but you feel like you are missing a piece of the puzzle?
It feels like magic.
You tried digging a little deeper to learn how it works under the hood,
you looked at the IL that the compiler generates, read a bit on the subject but still don’t understand it completely?
Don’t worry. It’s simple really!
Let’s try to distill it to it’s essence.

What if i told you that you could simulate the same feature even before the await keyword was introduced and all
you need from the language is Iterator blocks and lambdas?

The first step is understanding how Iterator blocks work. They are transformed by the compiler into State machines. Head over for a bit to the link above and let @JonSkeet do his magic explaining the details.

Good. Now lets see what smart people came up with (CCR Iterators as far back as 2005) to solve the callback hell that asynchrony produces.

CCR Iterators

Iterators are a C# 2.0 language feature that is used in a novel way by the Concurrency and Coordination Runtime (CCR). Instead of using delegates to nest asynchronous behavior, also known as callbacks, you can write code in a sequential fashion, yielding to CCR arbiters or other CCR tasks. Multi-step asynchronous logic can then be all written in one iterator method, vastly improving readability of the code. At the same time maintaining the asynchronous behavior, and scaling to millions of pending operations since no OS thread is blocked during a yield.

Here’s the simplest interface we can use to describe what Async means to us:

public interface IAsync
{
    void Run(Action continuation);
}

Note that i don’t deal with cancellation, exceptions or results at this point and that’s on purpose.
How can these two be combined to make asynchronous workflows look sequential?
Well, some brilliant guy at some point stood up and said :

What if we called MoveNext() inside the continuation of every Async call?

And that was it🙂

Here is the AsyncIterator logic :

    public static class Async
    {
        public static void Run(this IEnumerable&amp;lt;IAsync&amp;gt; asyncIterator)
        {
            var enumerator = asyncIterator.GetEnumerator();

            Action recursiveBody = null;
            recursiveBody = delegate
            {
                if (enumerator.MoveNext())
                    enumerator.Current.Run(recursiveBody);
            };

            recursiveBody();
        }

        public static IAsync Create(Action&amp;lt;Action&amp;gt; asyncAction)
        {
            return new AsyncPrimitive(asyncAction);
        }
    }

    public class AsyncPrimitive : IAsync
    {
        private readonly Action&amp;lt;Action&amp;gt; asyncAction;

        public AsyncPrimitive(Action&amp;lt;Action&amp;gt; asyncAction)
        {
            this.asyncAction = asyncAction;
        }

        public void Run(Action continuation)
        {
            asyncAction(continuation);
        }
    }

And here is what our code looks like.

        static void Main(string[] args)
        {
            MyAsyncWorkflow().Run();
        }

        public static IEnumerable&amp;lt;IAsync&amp;gt; MyAsyncWorkflow()
        {
            for (int i = 1; i &amp;lt; 4; i++)
            {
                Log(&amp;quot;Before Async &amp;quot; + i);
                var idx = i;
                yield return Async.Create((moveNext) =&amp;gt; { Log(&amp;quot;Running Async &amp;quot; + idx); moveNext(); });
            }

            Log(&amp;quot;Workflow done!&amp;quot;);
        }

Every time MoveNext() is called the code after the current yield return is called up until the next yield return.
This can happen at any point in time and from any thread because our code is decomposed and transformed into a state machine. At every yield return we give back the asynchronous operation that we want to run and the
AsyncIterator logic takes care of wiring everything up for us.

Here is the output when we run it :

AsyncIteratorRun

How does this relate to C#’s await feature? The IL produced by the compiler is built on this idea.
You can replace in your mind IAsync, IAsync.Run and yield return with Task, Task.ContinueWith and await.
Of course there are a lot more details involved with the full blown C# async/await implementation but the essence is the same.

I hoped this helped you demystify a little bit all the new async/await goodness🙂

That being said here is how professionals do it😛 : F# Computation Expressions and F# Asynchronous Workflows

Here are some links for the interested reader :

Stephen Toub’s -> Processing Sequences of Asynchronous Operations with Tasks

Tomas Petricek’s -> Asynchronous Programming in C# using Iterators

Jeffrey Richter’s -> Jeffrey Richter and his AsyncEnumerator

Jon Skeet’s -> Eduasync Series

WP7 vs WP8 Checkbox Style Changes

Hey. I had a small problem yesterday. Minor annoyance to be exact.

What were you trying to do?
Copy paste a WP7 control’s XAML, as is, to be used in a WP8 app.

What happened?
It didn’t work as is. A built-in control’s default style changed in WP8

Really? Which one?
The Checkbox. Well here, see for yourself :

WP7_WP8_Checkbox_Diff

What the what?? How’d that happen?
I think they just changed the controls style. Just like that.
Wait, i have a WinMerge report of the style differences as well here (D/L the html file and open it)

Tip: Open up Blend and click “Edit Template” on the Checkbox to get a copy of its style. Be sure
to do it inside the correct project each time.

Oh i see. How’d that make you feel?
I was a little bummed out..

I was bummed out

Why?
Why? Cause i am lazy and that’s extra work i didn’t want to do.

Relax. It happens. Why would Microsoft do that anyways?
Hell if i know..

Hell if i know

So what are you planning on doing?
Well, I don’t care for the new style. I want to keep the old one. At first i thought I’d make an App-wide StaticResource out of the old style.
Turns out that won’t seem to work easily. Here’s the exception i got by using the old style

CheckBoxStyleException

The new Checkbox doesn’t seem to like it’s old style anymore… Stay tuned for the solution.

-START UPDATE (WITH FIX AND BONUS TOOL) :
The fact that the old style didn’t immediately work on WP8 had to do obviously with a bunch
of missing or changed styles. Well after some dirty work here is the WP7-Like CheckBox Style for WP8 that makes it look like it did on WP7 WP7CheckBoxStyle.xaml.

<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

    <Color x:Key="WP7PhoneRadioCheckBoxCheckDisabledColor">#66000000</Color>
    <Color x:Key="WP7PhoneRadioCheckBoxDisabledColor">#66FFFFFF</Color>
    <Color x:Key="WP7PhoneRadioCheckBoxPressedBorderColor">#FFFFFFFF</Color>
    <Color x:Key="WP7PhoneRadioCheckBoxColor">#BFFFFFFF</Color>
    <Color x:Key="WP7PhoneRadioCheckBoxPressedColor">#FFFFFFFF</Color>
    <Color x:Key="WP7PhoneRadioCheckBoxCheckColor">#FF000000</Color>
    <SolidColorBrush x:Key="WP7PhoneRadioCheckBoxBrush" Color="{StaticResource WP7PhoneRadioCheckBoxColor}"/>
    <SolidColorBrush x:Key="WP7PhoneRadioCheckBoxCheckDisabledBrush" Color="{StaticResource WP7PhoneRadioCheckBoxCheckDisabledColor}"/>
    <SolidColorBrush x:Key="WP7PhoneRadioCheckBoxDisabledBrush" Color="{StaticResource WP7PhoneRadioCheckBoxDisabledColor}"/>
    <SolidColorBrush x:Key="WP7PhoneRadioCheckBoxPressedBorderBrush" Color="{StaticResource WP7PhoneRadioCheckBoxPressedBorderColor}"/>
    <SolidColorBrush x:Key="WP7PhoneRadioCheckBoxPressedBrush" Color="{StaticResource WP7PhoneRadioCheckBoxPressedColor}"/>
    <SolidColorBrush x:Key="WP7PhoneRadioCheckBoxCheckBrush" Color="{StaticResource WP7PhoneRadioCheckBoxCheckColor}"/>

    <Style x:Key="WP7PhoneButtonBase" TargetType="ButtonBase">
        <Setter Property="Background" Value="Transparent"/>
        <Setter Property="BorderBrush" Value="{StaticResource PhoneForegroundBrush}"/>
        <Setter Property="Foreground" Value="{StaticResource PhoneForegroundBrush}"/>
        <Setter Property="BorderThickness" Value="{StaticResource PhoneBorderThickness}"/>
        <Setter Property="FontFamily" Value="{StaticResource PhoneFontFamilySemiBold}"/>
        <Setter Property="FontSize" Value="{StaticResource PhoneFontSizeMediumLarge}"/>
        <Setter Property="Padding" Value="10,3,10,5"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="ButtonBase">
                    <Grid Background="Transparent">
                        <VisualStateManager.VisualStateGroups>
                            <VisualStateGroup x:Name="CommonStates">
                                <VisualState x:Name="Normal"/>
                                <VisualState x:Name="MouseOver"/>
                                <VisualState x:Name="Pressed">
                                    <Storyboard>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="ContentContainer">
                                            <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource PhoneBackgroundBrush}"/>
                                        </ObjectAnimationUsingKeyFrames>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="ButtonBackground">
                                            <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource PhoneForegroundBrush}"/>
                                        </ObjectAnimationUsingKeyFrames>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="BorderBrush" Storyboard.TargetName="ButtonBackground">
                                            <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource PhoneForegroundBrush}"/>
                                        </ObjectAnimationUsingKeyFrames>
                                    </Storyboard>
                                </VisualState>
                                <VisualState x:Name="Disabled">
                                    <Storyboard>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="ContentContainer">
                                            <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource PhoneDisabledBrush}"/>
                                        </ObjectAnimationUsingKeyFrames>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="BorderBrush" Storyboard.TargetName="ButtonBackground">
                                            <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource PhoneDisabledBrush}"/>
                                        </ObjectAnimationUsingKeyFrames>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="ButtonBackground">
                                            <DiscreteObjectKeyFrame KeyTime="0" Value="Transparent"/>
                                        </ObjectAnimationUsingKeyFrames>
                                    </Storyboard>
                                </VisualState>
                            </VisualStateGroup>
                        </VisualStateManager.VisualStateGroups>
                        <Border x:Name="ButtonBackground" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" CornerRadius="0" Margin="{StaticResource PhoneTouchTargetOverhang}">
                            <ContentControl x:Name="ContentContainer" ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" Foreground="{TemplateBinding Foreground}" HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" Padding="{TemplateBinding Padding}" VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"/>
                        </Border>
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
    <Style x:Key="WP7PhoneRadioButtonCheckBoxBase" BasedOn="{StaticResource WP7PhoneButtonBase}" TargetType="ToggleButton">
        <Setter Property="Background" Value="{StaticResource WP7PhoneRadioCheckBoxBrush}"/>
        <Setter Property="BorderBrush" Value="{StaticResource WP7PhoneRadioCheckBoxBrush}"/>
        <Setter Property="FontSize" Value="{StaticResource PhoneFontSizeMedium}"/>
        <Setter Property="FontFamily" Value="{StaticResource PhoneFontFamilyNormal}"/>
        <Setter Property="HorizontalContentAlignment" Value="Left"/>
        <Setter Property="VerticalContentAlignment" Value="Center"/>
        <Setter Property="Padding" Value="0"/>
    </Style>
    <Style x:Key="WP7CheckBoxStyle" BasedOn="{StaticResource WP7PhoneRadioButtonCheckBoxBase}" TargetType="CheckBox">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="CheckBox">
                    <Grid Background="Transparent">
                        <VisualStateManager.VisualStateGroups>
                            <VisualStateGroup x:Name="CommonStates">
                                <VisualState x:Name="Normal"/>
                                <VisualState x:Name="MouseOver"/>
                                <VisualState x:Name="Pressed">
                                    <Storyboard>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="CheckBackground">
                                            <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource WP7PhoneRadioCheckBoxPressedBrush}"/>
                                        </ObjectAnimationUsingKeyFrames>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="BorderBrush" Storyboard.TargetName="CheckBackground">
                                            <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource WP7PhoneRadioCheckBoxPressedBorderBrush}"/>
                                        </ObjectAnimationUsingKeyFrames>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Fill" Storyboard.TargetName="CheckMark">
                                            <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource WP7PhoneRadioCheckBoxCheckBrush}"/>
                                        </ObjectAnimationUsingKeyFrames>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Fill" Storyboard.TargetName="IndeterminateMark">
                                            <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource WP7PhoneRadioCheckBoxCheckBrush}"/>
                                        </ObjectAnimationUsingKeyFrames>
                                    </Storyboard>
                                </VisualState>
                                <VisualState x:Name="Disabled">
                                    <Storyboard>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="CheckBackground">
                                            <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource WP7PhoneRadioCheckBoxDisabledBrush}"/>
                                        </ObjectAnimationUsingKeyFrames>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="BorderBrush" Storyboard.TargetName="CheckBackground">
                                            <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource PhoneDisabledBrush}"/>
                                        </ObjectAnimationUsingKeyFrames>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Fill" Storyboard.TargetName="CheckMark">
                                            <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource WP7PhoneRadioCheckBoxCheckDisabledBrush}"/>
                                        </ObjectAnimationUsingKeyFrames>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Fill" Storyboard.TargetName="IndeterminateMark">
                                            <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource WP7PhoneRadioCheckBoxCheckDisabledBrush}"/>
                                        </ObjectAnimationUsingKeyFrames>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="ContentContainer">
                                            <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource PhoneDisabledBrush}"/>
                                        </ObjectAnimationUsingKeyFrames>
                                    </Storyboard>
                                </VisualState>
                            </VisualStateGroup>
                            <VisualStateGroup x:Name="CheckStates">
                                <VisualState x:Name="Checked">
                                    <Storyboard>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility" Storyboard.TargetName="CheckMark">
                                            <DiscreteObjectKeyFrame KeyTime="0">
                                                <DiscreteObjectKeyFrame.Value>
                                                    <Visibility>Visible</Visibility>
                                                </DiscreteObjectKeyFrame.Value>
                                            </DiscreteObjectKeyFrame>
                                        </ObjectAnimationUsingKeyFrames>
                                    </Storyboard>
                                </VisualState>
                                <VisualState x:Name="Unchecked"/>
                                <VisualState x:Name="Indeterminate">
                                    <Storyboard>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility" Storyboard.TargetName="IndeterminateMark">
                                            <DiscreteObjectKeyFrame KeyTime="0">
                                                <DiscreteObjectKeyFrame.Value>
                                                    <Visibility>Visible</Visibility>
                                                </DiscreteObjectKeyFrame.Value>
                                            </DiscreteObjectKeyFrame>
                                        </ObjectAnimationUsingKeyFrames>
                                    </Storyboard>
                                </VisualState>
                            </VisualStateGroup>
                        </VisualStateManager.VisualStateGroups>
                        <Grid Margin="{StaticResource PhoneTouchTargetLargeOverhang}">
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="32"/>
                                <ColumnDefinition Width="*"/>
                            </Grid.ColumnDefinitions>
                            <Grid Grid.Column="0">
                                <Border x:Name="CheckBackground" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{StaticResource PhoneBorderThickness}" Background="{TemplateBinding Background}" HorizontalAlignment="Left" Height="32" IsHitTestVisible="False" VerticalAlignment="Center" Width="32"/>
                                <Rectangle x:Name="IndeterminateMark" Fill="{StaticResource WP7PhoneRadioCheckBoxCheckBrush}" HorizontalAlignment="Center" Height="16" IsHitTestVisible="False" Visibility="Collapsed" VerticalAlignment="Center" Width="16"/>
                                <Path x:Name="CheckMark" Data="M0,123 L39,93 L124,164 L256,18 L295,49 L124,240 z" Fill="{StaticResource WP7PhoneRadioCheckBoxCheckBrush}" FlowDirection="LeftToRight" HorizontalAlignment="Center" Height="21" IsHitTestVisible="False" Stretch="Fill" StrokeThickness="3" StrokeLineJoin="Round" Visibility="Collapsed" VerticalAlignment="Center" Width="23"/>
                            </Grid>
                            <ContentControl x:Name="ContentContainer" ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" Grid.Column="1" Foreground="{TemplateBinding Foreground}" HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="12,0,0,0" Padding="{TemplateBinding Padding}" VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"/>
                        </Grid>
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</ResourceDictionary>

Here is a screenshot that shows off 1) how to use the Style and 2) how it actually looks/works:

WP7_WP8_FixedStyle_Vertical
I needed some help for that painful process of finding out what style changed and how between WP7 and WP8 thats why i built a small tool :

WPThemeReviewerTool1 WPThemeReviewerTool2

I call it “WinPhone Theme Reviewer” , it targets WP8 only for now and you can download the source or xapfile.
What i did, essentially, is include MS’s Theme xaml files located “C:\Program Files (x86)\Microsoft SDKs\Windows Phone\vXX\Design\ThemeResources.xaml” for both WP71 and WP8 in the App.

Enjoy🙂


-END UPDATE


Wait. That probably means even more default styles might be messed up..
know…We’ll just have to wait and see..

Btw. You know you are talking to yourself right?
….

WP7 App on WP8 Breaking Changes – Part 1 – WebRequest’s Referer Changes

Well, after testing a WP7 app running on WP8 guess what happened…It worked differently on WP8.
The issue as described was : Almost all of the thumbnails stopped showing when the user was logged in.

That was an interesting one. It was obvious it was an MS bug (check out the other one I discovered as well here).

Btw let me say that the MS guys have done an amazing job with WP8! They worked really hard to make the deadlines and try to keep that huge promise that all WP7 apps would automagically run as-is on WP8. Huge effort from their part.

Time to relax back and do some bug-hunting🙂

Thumbnails mean WebRequests. The ones that failed were shown by setting the UriSource on a BitmapImage. We need to go ask the BitmapImage what goes wrong with the requests when running inside a WP8 device. So lets setup fiddler so we can check the traffic. Note that my PC and the WP8 device were connected to the same Wifi network.

Below you can see how to setup the proxy on the phone’s wifi connection (tap on it for settings).

Great. Now I was able to compare the requests made from a WP7 and WP8 device.

Long story short, I was able to pinpoint the issue and it had to do with the fact that

On WP8 MS changed the way they handle/send Referer headers in WebRequests for both  BitmapImage and WebClient

Why my problem occurred : As it turns out the thumbnail requests, once logged in, are authenticated and in that case the server uses the Referer in order to authenticate the request. If the referer is different than the one you used to log in (through a WebClient) the request will fail. So when a WP7 app runs in WP7 device both the BitmapImage and the WebClient send the identical referer (Applications/Installl) but when a WP7 app is running on WP8 then BitmapImage sends a different Referer than what the WebClient sent to the server while authenticating resulting in all thumbnails to fail.

Lets setup a small test case to highlight and visualize the issue.

Here is the test we are going to run :

We are going to try it in 3 scenarios so we can see the results. The scenarios are :

  1. A WP7 app running on WP7
  2. A WP7 app running on WP8
  3. A WP8 app running on WP8

And now here are the results in order :

WP7 app running on WP7

Figure 1 : BitmapImage request (WP7 on WP7)

Figure 2 : WebClient request (WP7 on WP7)

WP7 app running on WP8
WP7AppOnWP8_BitmapImage_Req_PROBLEM

Figure 3 : BitmapImage request (WP7 on WP8) changed!

WP7AppOnWP8_WebClient_Req

Figure 4 : WebClient request (WP7 on WP8) as normal

WP8 app running on WP8
WP8AppOnWP8_BitmapImage_Req

Figure 5 : BitmapImage request (WP8 on WP8)

Figure 6 : WebClient request (WP8 on WP8).

The problem should be really obvious by now.

Concern #1 : I pretty much can’t do anything to workaround this issue. Changing the whole app to manually download all thumbnails is not an option.

Concern #2 : what should we do from now on WP8 for new Apps as far as Referer’s are concerned?

Do we need to use Data/Programs from now on?
Does that mean that for new apps on WP8 we will have to now manually inject the Referer ourselves on all webrequests? And so on…

I have create a forum thread on Microsoft’s WP forums on the issue here

A word of caution on argument validation in Async methods

I have been noticing around in some blogposts and code snippets a pattern being used when validating arguments in Task-returning async methods and that is returning the ArgumentException as part of the Task
instead of immediately failing (directly raising the exception). Something didn’t feel right so i thought i’d try it
out.

Let’s start with defining these 2 async method variations for argument validation :

The first one assigns the exception to the returned Task and the second one immediately raises it the good old-fashioned way.

Next we write our tests that cover the usage scenarios of our async methods :

Both tests try to call our async methods with a null argument by both awaiting and not awaiting them (fire and forget).
And here is what we get after running it :

As expected, we notice that the thrown ,argument validating, exception when assigned to the returning Task and when not awaited by the caller is completely lost! Like it never happened. The Task “swallowed” it.

In most cases this is the expected behavior, when the exception is part of your Task logic and isn’t awaited, but these kind of exceptions should not go unnoticed! They represent usage errors and should be communicated to the caller fast and always. These can be your usual pre-conditions like argument validation, state validation etc.

One of the lessons from this is that you should also be aware of the implications of your async method not being awaited.

I highly recommend reading the “Task-Based Asynchronous Pattern” document from Microsoft here where
it states :

Exceptions

An asynchronous method should only directly raise an exception to be thrown out of the MethodNameAsync call in response to a usage error*. For all other errors, exceptions occurring during the execution of an asynchronous method should be assigned to the returned Task. This is the case even if the asynchronous method happens to complete synchronously before the Task is returned. Typically, a Task will contain at most one exception.  However, for cases where a Task is used to represent multiple operations (e.g. Task.WhenAll), multiple exceptions may be associated with a single Task.

(*Per .NET design guidelines, a usage error is something that can be avoided by changing the code that calls the method. For example, if an error state results when a null is passed as one of the method’s arguments, an error condition usually represented by an ArgumentNullException, the calling code can be modified by the developer to ensure that null is never passed. In other words, the developer can and should ensure that usage errors never occur in production code.)

OrientationHelper for Windows Phone and Windows 8

This is a small utility to help with WP7,WP8 and Windows Store app development where there is a need to design your UX in order to support multiple screen sizes and orientations.
(Phew i almost said Metro Style..Wait..Damn it)

It is inspired by ‘LayoutAwarePage’ , an utility class included in the templates for Windows Store Apps.

On the Windows Phone side there are 6 orientation states:

  • Landscape
  • LandscapeLeft
  • LandscapeRight
  • Portrait
  • PortraitUp
  • PortraitDown

On the Windows Store side there are 4 view states :

  • Filled
  • Snapped
  • FullScreenLandscape
  • FullScreenPortrait

Before we go into details here is an example of the utility working on the Phone in Portrait mode :
On the left side we have setup our utility to automatically run some arbitrary scale animations ,defined in XAML, based on the current Orientation or ViewState. There’s nothing sophisticated in the screenshots below. Simply showing off the functionality.

Here you can see another one automatically running on the left side in Landscape mode.

Similarly on the Windows 8 side:

(FullScreenPortrait)

(FullScreenLandscape)

(Filled)

(Snapped)

What the designer needs to do is describe the UI (Xaml) for all screens and for all possible orientations/view states in order to provide a good UX. There is no clear pattern/guidelines on how this should be done although LayoutAwarePage gives us a good ‘clean’ solution by taking advantage of a well known proven XAML solution called the VisualStateManager. We are, after all, trying to tackle switching between multiple visual states so VisualStateManager sounds like a natural fit. And it is.

The basic idea is , similar to creating Custom Controls, to declare all views for all supported orientations/view states inside the same XAML file (what if the UI is composite though?) and use VisualStates, one for each specific orientation/view state, to describe the UI changes needed to transition between View designs. We will then let VisualStateManager do it’s work by asking it programmatically to switch between states when the platform notifies us of a change in orientation/view state.

What the developer needs to do is manually listen for orientation/view state changes for all visible screens
and call VisualStateManager to transition the current screen to the current view state.

This programmatic part of the developer seems like a lot of manual work that could be done automatically.
There’s gonna be a lot of code-behind spread around listening for the same event and dealing manually
with VisualState changing (or manually enabling/disabling controls, running animations etc etc if we didnt
use VisualStateManager)
Unfortunately no one can help the poor designer (developer?) that has to rewrite/redesign the whole UI
again and again. It has to happen.

LayoutAwarePage solves it by creating a Page base class for Metro style apps.
This utility is instead an attached property and supports Pages, user controls and custom controls. Haven’t made a sample with custom controls but it should be the same as user controls.
What if though i want to create a reusable custom control/user control and i want to have IT define how it should look on different orientations/view states instead of forcing the consumer/user of the control to do it.
Sometimes ,me as a user of a control, might need to tweak more stuff “inside” the control to make it look right. Lets say for example that i have a control that defines two buttons side by side ,stretched, that fill my Landscape view across nicely. I would have liked if the control itself switched them to be stacked (one on top of the other) when in Portrait mode. I can’t do that though unless the control supported that. Note that it would be best if the control supported that but didn’t enforce it.I the user would like to have control over when and if the control is allowed to auto-adapt by itself or i will solve it outside or the control. The utility supports this scenario by letting me decide whether or not to set the attached property OrientationHelper.IsActive on the control that enables it’s orientation/view state support if of course the control has defined the appropriate VisualStates.

The solution seemed transferable to Windows Phone as well and so the utility comes in 3 assemblies supporting WP7/WP8/WIN8.

What we need to do in order to use it is
1) set the attached property OrientationHelper.IsActive=”true” on a Page, UserControl or CustomControl
2) Define one VisualStateGroup on the orientation-aware control named “PageOrientationStates” for WP
and “ApplicationViewStates” for Win8.
3) Define one VisualState for each supported Orientation/ViewState. The VisualState name should match exactly the name of the Orientation/ViewState. For example i would name “Filled” the VisualState that is meant to design my UI when in Filled state.

Setting the attached property :
In this case the UserControl set’s it for demo purposes .It’s overridable.

Defining the VisualStates (For Win8) :

Quick tip : VisualStateGroups and VisualStateManager , i found, work *only* when defined/attached on the
RootElement of your Page or UserControl. Which means it wont work if you declare a control inside a Page, declare VisualStates on it and try to call VSM on that specific control.

Here’s the code for the OrientationHelper.

using System;
using System.Collections.Generic;
using System.Linq;

#if WINDOWS_PHONE
using System.Windows;
using System.Windows.Controls;
using Microsoft.Phone.Controls;
using Orientation = Microsoft.Phone.Controls.PageOrientation;
#else
using Windows.UI.Core;
using Windows.UI.ViewManagement;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Orientation = Windows.UI.ViewManagement.ApplicationViewState;
#endif

namespace OrientationHelper
{
    public static class OrientationHelper
    {
#if WINDOWS_PHONE
        private const String VisualStateGroupName = "PageOrientationStates";
#else
        private const String VisualStateGroupName = "ApplicationViewStates";
#endif

        #region IsActive DP

        public static readonly DependencyProperty IsActiveProperty =
            DependencyProperty.RegisterAttached("IsActive", typeof (bool), typeof (OrientationHelper),
                                                new PropertyMetadata(default(bool), OnIsActivePropertyChanged));

        public static void SetIsActive(UIElement element, bool value)
        {
            element.SetValue(IsActiveProperty, value);
        }

        public static bool GetIsActive(UIElement element)
        {
            return (bool) element.GetValue(IsActiveProperty);
        }

        private static void OnIsActivePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var control = d as Control;
            if (control == null)
                return;

            SetupOrientationAwareControl(control, (bool)e.NewValue);

#if WINDOWS_PHONE
            //The control itself can be a page.In every case we need to retry until the containing page is loaded.
            control.Loaded += OnControlLoaded;
#endif

        }

        #endregion

#if WINDOWS_PHONE
        //Note: On the phone side Orientation is Page-specific so we keep the orientation aware controls
        //on the page itself using a Dependency Property
        #region OrientationAwareControls Private DP

        private static readonly DependencyProperty OrientationAwareControlsProperty =
            DependencyProperty.RegisterAttached("OrientationAwareControls", typeof (IList),
                                                typeof (OrientationHelper), null);

        private static void SetOrientationAwareControls(DependencyObject element, IList value)
        {
            element.SetValue(OrientationAwareControlsProperty, value);
        }

        private static IList GetOrientationAwareControls(DependencyObject element)
        {
            return (IList) element.GetValue(OrientationAwareControlsProperty);
        }

        #endregion
#else
        //Note: On the Windows 8 side Orientation is global
        private static IList<WeakReference> orientationAwareControls;
#endif

        private static void SetupOrientationAwareControl(Control control, bool isActive)
        {
#if WINDOWS_PHONE
            var page = FindParentPage(control);
            if (page == null)
                return;
            if (isActive)
            {
                //Add the orientation aware control to the list stored on the Page
                if (GetOrientationAwareControls(page) == null)
                {
                    SetOrientationAwareControls(page, new List());
                    //Start listening for changes
                    page.OrientationChanged += PageOnOrientationChanged;
                }
                if (!GetOrientationAwareControls(page).Contains(control))
                    GetOrientationAwareControls(page).Add(control);
                UpdateOrientationAwareControls(new[] { control }, page.Orientation); //Update this control only

            }
            else
            {
                var orientationAwareControls = GetOrientationAwareControls(page);
                if (orientationAwareControls != null)
                {
                    if (orientationAwareControls.Contains(control))
                    {
                        orientationAwareControls.Remove(control);
                        control.Loaded -= OnControlLoaded;
                    }
                    //Do cleanup for this page if there are no more controls
                    if (!orientationAwareControls.Any())
                    {
                        SetOrientationAwareControls(page, null);
                        page.OrientationChanged -= PageOnOrientationChanged;
                    }
                }
            }
#else
            if (isActive)
            {
                if (orientationAwareControls == null)
                    orientationAwareControls = new List();

                if (!GetOrientationAwareControls().Contains(control))
                {
                    orientationAwareControls.Add(new WeakReference(control));
                    // Note: On the Windows 8 side, probably due to aggressive optimizations,
                    // if the control is not named then when changing orientations/view states any
                    // WeakReference to that control will show it as GCed!
                    // Disclaimer : I ONLY TESTED ON THE SIMULATOR!!
                    if (string.IsNullOrEmpty(control.Name))
                    {
                        control.Name = Guid.NewGuid().ToString();
                    }
                    control.Loaded += OnControlLoaded;

                    if (control.Parent != null)
                    {
                        UpdateOrientationAwareControls(new[] { control }, ApplicationView.Value);
                    }
                }
                if (GetOrientationAwareControls().Any())
                {
                    //TODO: Handle Window changes (Closed)
                    Window.Current.SizeChanged += OnWindowSizeChanged;
                }

            }
            else
            {
                if (GetOrientationAwareControls().Contains(control))
                {
                    var controlWeakRef = orientationAwareControls.Single(weak => control.Equals(weak.Target));
                    orientationAwareControls.Remove(controlWeakRef);
                    control.Loaded -= OnControlLoaded;
                }
                if (!GetOrientationAwareControls().Any())
                {
                    orientationAwareControls = null;
                    Window.Current.SizeChanged -= OnWindowSizeChanged;
                }
            }
#endif
        }

        private static void OnControlLoaded(object sender, RoutedEventArgs routedEventArgs)
        {
            var control = sender as Control;
#if WINDOWS_PHONE
            SetupOrientationAwareControl(control, GetIsActive(control));
#else
            UpdateOrientationAwareControls(new[] { control }, ApplicationView.Value);
#endif
        }

#if WINDOWS_PHONE

        private static PhoneApplicationPage FindParentPage(FrameworkElement el)
        {
            FrameworkElement parent = el;
            while(parent != null)
            {
                if (parent is PhoneApplicationPage)
                    return parent as PhoneApplicationPage;
                parent = parent.Parent as FrameworkElement;
            }
            return null;
        }

        private static void PageOnOrientationChanged(object sender, OrientationChangedEventArgs e)
        {
            var page = sender as PhoneApplicationPage;
            UpdateOrientationAwareControls(GetOrientationAwareControls(page), page.Orientation); //Update all controls
        }
#else
        private static void OnWindowSizeChanged(object sender, WindowSizeChangedEventArgs windowSizeChangedEventArgs)
        {
            UpdateOrientationAwareControls(GetOrientationAwareControls(), ApplicationView.Value);
        }
        private static IEnumerable<Control> GetOrientationAwareControls()
        {
            if(orientationAwareControls == null || !orientationAwareControls.Any())
                return Enumerable.Empty();

            IList<Control> aliveControls = new List<Control>();
            foreach (var controlWeakRef in orientationAwareControls.ToList())
            {
                if (controlWeakRef.IsAlive)
                    aliveControls.Add(controlWeakRef.Target as Control);
                else
                    orientationAwareControls.Remove(controlWeakRef);
            }
            return aliveControls;
        }
#endif

        private static void UpdateOrientationAwareControls(IEnumerable controls, Orientation orientation)
        {
            if (controls == null || !controls.Any())
                return;

            foreach (var control in controls)
            {
                VisualStateManager.GoToState(control, GetVisualStateName(orientation), true);
            }
        }

        private static String GetVisualStateName(Orientation orientation)
        {
            return orientation.ToString();
        }
    }
}

Here’s the whole solution : OrientationHelper.zip

Feel free to comment if you found it useful or found any issue.

Au revoir

A .NET Dev’s baby steps trying to share native code between Win8 and WP8

This is a walkthrough of what i had to do to setup native code sharing between Windows 8 and Windows Phone 8 (using the leaked WP8 SDK). My knowledge of the native world is quite limited and there might be other better ways of doing it. Feel free to comment if you know more about the subject and help out this poor .NET dev🙂

First we create our Native C++ WinRT Component :

Add New Windows Runtime Component Project

Then we create our Native C++ Phone Runtime Component :

Next we delete from both projects the autogenerated files. From the WinRT project delete the files named Class1.cpp and Class1.h and from the PhoneRT project delete the files named NativeSharedPhoneRT.cpp and NativeSharedPhoneRT.h.

What we need next is a simple class that we will want to share between the two projects. Lets call it MySharedClass. We will create it only on the WinRT side and we will link to it from the PhoneRT side.

I am expecting that i can use preprocessor flags in the same manner that we used to do between Silvelight/WPF and Windows Phone. So the next question is “how do i define my preprocessor directives in C++ projects”?
These simple steps worked for me :

  1. Open the properties of the NativeSharedWinRT project and go to “Configuration Properties -> C/C++ -> Command Line
  2. Enter “/D “_WinRT”” (without the outside quotes) in  “Additional Options” and click Apply.

Screenshot below :

(Note: the only reason i named the directive with an underscore is because the debug directive in one of the templates was named _DEBUG.Thought it might be a convention or something)
As jalfdjalf pointed out directives starting with underscores are reserved (makes sense) so its OK to name our own as we wish (i.e PhoneRT, WinRT).Btw i used PhoneRT instead of the more “official” WinPRT for the phone because its a lot more distinguishable from WinRT.

Do the same thing for the NativeSharedPhoneRT project but add this “/D “_PhoneRT””  instead in the Additonal Options.
Great. Now we have setup our preprocessor directives for both our shared projects. Time to create the shared class. Go to the NativeSharedWinRT project and add an empty MySharedClass.cpp file and an empty MySharedClass.h file. Then go to the NativeSharedPhoneRT project, click “Add existing item” and navigate inside the NativeSharedWinRT folder to locate the newly created files and select those. These files are now linked and the project structure should look like this :

(Note: I tried linking the pch.cpp and pch.h files as well but VS and the compiler didnt like that for
some reason so i kept them unlinked in order to move one)

Ok so far. Now lets add code to our shared class and see how we can start sharing.
Below is only a screenshot of what the code inside our files should be but you will be able to
download the source code and copy paste directly (see download link at end of post).

Notice how opening the header file from inside the WinRT project that the _WinRT directive is active but not the _PhoneRT one just as we wanted. SharedMethodAsync is a WinRT-Style asynchronous method exposed to both WinRT and PhoneRT.

I had planned to also show off how projections worked in the WinRT world but i couldn’t get it to work easily.The plan was to expose a WinRT type like IMap or IIterable and see how they show up projected in C#.

Here is our .cpp file (opened from inside the NativeSharedPhoneRT project) :

Now its time to create our C# clients (one for WinRT and one for PhoneRT) that will consume our shared native libraries.
First is the WinRT C# Client :

Once created click “Add Reference” on it and select the NativeSharedWinRT project.

Big pause here! Can you say “where’s my P/Invoke dude?”  :)
Now that’s what i call seamless.
Small note.Never forget that the interop cost is ALWAYS there when going back and forth from native <-> managed.Keep in mind that usually there is an interop cost when going native <-> managed and
that applies to WinRT as well although Microsoft has done a lot of work to minimize it.

Then is our PhoneRT C# Client :

Once created click “Add Reference” on it and select the NativeSharedPhoneRT project.

This is how the project structure should look now :

Finally lets see what the code looks like from both client projects.
This is what we get from the Phone Client :

and here is what we get from the Win8 Client :

And that’s it! That was certainly fun🙂

Source code for this post is here