DLL / Reference hell with #WP8 #SL81 and #WinRT component

Over the last month, I have gone back to “AlarmClock” app (my 3rd Windows Phone app from back in 2011). I have updated it to render time updates on live tile. In fact I am quite proud the mechanism I use. I additionally provided 50 downloadable font packs that users can choose from (purchasable in a set of 10).

Original solution
The update mechanism was initially based on Silverlight Background Task. The tile update mechanism of course updates tile based on local time. However a user reported that when travelling between timezones, the tiles kept showing previous timezone times until the next background task run started pushing new ones based on new local time.

I deliberated on this and came to the conclusion that somewhere something was fishy.. its possible that Tile updates are actually scheduled on UTC as opposed to local time or maybe I just don’t understand it. Either way, I had to fix this issue

Solution 2: Fix for Timezone change
The new windows phone 8.1 introduced a bunch of new WinRT API that included API for Background task including those that run on Timezone change. So I dumped SL based Background Task and went full stream with WinRT component. Added 2 WinRT classs on for Timer and another for Timezone and this worked great.

Another user wanted the clock and tile updates to support multiple Timezones – wanted to pin Hong Kong and Seattle. My app so far only supported local device timezone.

Soluion 3 – Multiple Timezone support

.NET 4.5 comes with TimeZoneInfo class.This provides a nice method GetSystemTimeZones which lists all timezones and make it possible to convert between those. However Windows Phone .NET Runtime does not come with this and there is not suitable WinRT API either. Yay!!
Oren Novotny created a good Win32 wrapper which works on both WP8, WP81, SL81 and WinRT
I fired up Nuget Package Manager and searched for timezone..found Timezone conversion between WinRT and PCL.. Added a reference to the App and reworked it to support user selectable timezone etc. This required me to select target between x86 and ARM – any CPU no longer an option.

Next step?? Add Timezone helper reference to WinRT component. Bang bang bang.. nugget sorted it all out.. that was easy.. modified the background processor to update all tiles with correct timezone times!! nice :) What could possibly go wrong ?

Hit F6, (Old school.. modified VS 2013 to build o F6 like before).. all good. Hit F5… wait for it !!!!

Runtime exception – File not found System.Runtime.InteropService.. quick search showed reference conflict..

Step 1) Set WinRT component to x86 instead of Any CPU.. maybe that will do the trick!!!

Nope far from it… Result System.BadImageFormatException thown when trying to run the app.

Step 2) Download code and make a part of existing WinRT component..

Nope still the same error(s)

While deliberating, realised that I called code from Background Task directly from my app.. 3rd trial

Step 3)

Remove calls to code in Background Task from App
Nuget Reference to App
Code within WinRT component for internal use
App – x86 / ARM target
WinRT component – Any CPU tagt

Bingo.. It all work as advertised!!

Took me day to figure try out various options

App tile transparency for WP8.1 apps #wpdev

One of my popular lines is “Don’t throw shit around.. what goes around comes around!” and rightly so. A few weeks back I was making fun of @dvlup for blogging about how to create transparent tiles for the WP apps :)

I know the irony isn’t lost on me. The idea is with WP8 apps, you create tile images which are transparent png with white bits.. if you had a star or a clock that would be white, the rest would be transparent and you used this. This would make your app’s tile transparent and if you had a fancy background, you would see through the tile.

Fast forward today, I was testing WP8.1 update to my alarm clock app. What does it do ? well shows you tile update every minute with a nicely rendered tile. and yes I made the tile transparent. But the tile comes up as grey.. WTH

alarmclock1

so I start looking around and I remember that Windows 8 app manifest had a background color, Open the Package.appmanifest and I find this

<m3:VisualElements
    DisplayName="AlarmClock"
    Square150x150Logo="Assets\SquareTile150x150.png"
    Square44x44Logo="Assets\Logo.png"
    Description="AlarmClock"
    ForegroundText="light"
    BackgroundColor="#464646">

hmmm no alpha value to make it transparent. So I tried to set BackgroundColor to Transparent.. nope.. transparent ? Bingo!!

<m3:VisualElements
    DisplayName="AlarmClock"
    Square150x150Logo="Assets\SquareTile150x150.png"
    Square44x44Logo="Assets\Logo.png"
    Description="AlarmClock"
    ForegroundText="light"
    BackgroundColor="transparent">

alarmclock2
Now if you used transparent png for tiles, your WP 8.1 app’s tiles are transparent.

Where did the SystemTray vanish with #WinPRT #wpdev?

With Silverlight WP8 API, SystemTray is exposed in PhoneApplicationPage through Microsoft.Phone.Shell.

<phone:PhoneApplicationPage
    shell:SystemTray.IsVisible="True" 
    shell:SystemTray.BackgroundColor="AliceBlue"
    shell:SystemTray.ForegroundColor="Black"
    shell:SystemTray.Opacity="0.75">
    <shell:SystemTray.ProgressIndicator>
        <shell:ProgressIndicator />
    </shell:SystemTray.ProgressIndicator>
</phone:PhoneApplicationPage>
SystemTray.BackgroundColor = Colors.Cyan;
SystemTray.ForegroundColor = Colors.White;
SystemTray.IsVisible = true;
SystemTray.Opacity = 0.8;
SystemTray.ProgressIndicator = new ProgressIndicator() { IsIndeterminate = true, IsVisible = true };

it was very easily done through xaml itself. You could do it from codebehind by accessing static properties of SystemTray class.
However with WinPRT, the Page class does not expose SystemTray and now it lives as Windows.UI.ViewManagement.StatusBar.
No xaml declarative business here.

var statusBar = StatusBar.GetForCurrentView();
statusBar.BackgroundColor = Colors.Black;
statusBar.BackgroundOpacity = 0.8;
statusBar.ForegroundColor = Colors.White;
statusBar.ProgressIndicator.Text = "loading";
await statusBar.ShowAsync();

If I find anything declarative, I will post those at a later date.

Backbutton handling with #winprt and Windows Phone 8.1 #wpdev

Back with WP8 and Silverlight API, handling hardware back button was easy peasy. By default, PhoneApplicationPage exposed an eventhandler called BackKeyPress. Developers could chose to subscribe to this event handler and handle the back button.

<phone:PhoneApplicationPage shell:SystemTray.IsVisible="True" BackKeyPress="PhoneApplicationPage_BackKeyPress">
...
...
...
</phone:PhoneApplicationPage>
private void PhoneApplicationPage_BackKeyPress(object sender, System.ComponentModel.CancelEventArgs e)
{
    if (this.DrawingCanvas.Visibility == System.Windows.Visibility.Visible)
    {
        this.DrawingCanvas.Visibility = this.ColorSlider.Visibility = System.Windows.Visibility.Collapsed;
        this.piWords.IsLocked = false;
        e.Cancel = true;
    }
}

As you can see, in the back key press, I check to see if certain view is being shown and if so, I hide it that rather than navigating page backstack.

That was Silverlight / WP API.. how would we do that in WP8.1 / WinPRT API ?
Windows.Phone.UI.Input namespace contains a class called HardwareButtons. just remember this is WP8.1 WinPRT API only – not supported on Windows store apps. Sadly no XAML wiring up.. lets go to codebehind and subscribe to it


public MainPage()
{
    this.InitializeComponent();

    this.NavigationCacheMode = NavigationCacheMode.Required;

    HardwareButtons.BackPressed += HardwareButtons_BackPressed;
}

void HardwareButtons_BackPressed(object sender, BackPressedEventArgs e)
{
    if (some_condition)
    {
        e.Handled = true;
    }
}

That’s about it.. thank goodness I still have Dev preview documentation lying around :)

Color Picker for #win8dev

I use colour picker across multiple projects on both windows phone and windows 8. Allowing users a choice of colour is a good thing from experience perspective. Whilst I found a number of solutions for Windows Phone, I never really found much for Windows 8.

Last year I ported the Coding4Fun ColorHexagonPicker to use with my TableClock app.Recenly working on Scribble I needed a broader range of colours and I decided to create an appbar control that conveniently lives in AppBar.

I have uploaded the source to Github. Feel free to fork and extent.

Screenshot (1)

 

WinRT and pointer manipulation #win8dev #winrtdev

We all know how Windows 8 introduced touch as a first class member in user input. If you have used Windows 8 it feels intuitive to touch.. hell I used to touch my non-touch laptop occasionally and not because I wanted to fondle it :)

Rewinding a bit.. in Silverlight and Windows Phone, we had a nice historic Touch.FrameReported event. This was the fastest way to detect pointer / touch interaction on the screen. It also supported multi-touch detection by means of exposing TouchFrameEventArges.GetTouchPoints.

We also know how famously .NET components were sliced and diced (lets leave it for some other time when I have had a drink or two). So its only natural that WinRT 1.0 native XAML didn’t have Touch.FrameReported.

The other high level mechanism for touch event detection was the set of manipulation events
* UIElement.ManipulationStarted
* UIElement.ManipulationDelta and
* UIElement.ManipulationCompleted

These made it to WinRT 1.0 XAML.. However there were changes. Now it comes armed with ManipulationMode.

The MEME RTFM definitely applies to me – I never read the manual… When we had proper MSDN lib for documentation it was all good.. now documentation is all over the place.. (Damn it… need to focus more… another thing to talk over a drink).

So what happened.. why trying to detect touch / pointer events, I started using Manipulation events but hell no.. the event’s just wouldn’t get called.. The mode has tons of options but to handle it yourself you need to set the ManipulationMode to All. Someone remind me something.. If I declare a bleeding event handler.. isn’t my intention already pretty clear ? (Something every logical from .NET lost in translation on its way to WinRT design).

So eventually I got that to work by setting ManipulationMode to All. Surprise surprise, the manipulation event args only expose a few things like Position and PointerType…So this definitely can’t do multi-touch.. sure it will detect all the touch inputs but it can’t tell the difference the two fingers!!

Time to give it the middle one and start looking at alternatives. Previously in WPF / Silverlight we had Mice events
* UIElement.MouseLeftButtonDown
* UIElement.MouseLeftButtonUp
* UIElement.MouseMove

Those didn’t directly made it. WinRT merged Mice and Touch events into Pointer events. So now we have
* UIElement.PointerPressed
* UIElement.PointerReleased
* UIElement.PointerMoved

The PointerRoutedEventArgs that are passed to the event handers not only give you current position and intermediate positions, they also give you access to Pointer associated with the event. Each touch point / mice button gets a unique id. This way you can detect activity of each touch points over the screen.

The post is very verbose and lot of gibberish.. let me throw some code snippet to lighten it up :)

private void LayoutRoot_PointerMoved(object sender, PointerRoutedEventArgs e)
{
    Point position2 = e.GetCurrentPoint(this.LayoutRoot).Position;
    Pointer pointer2 = e.Pointer;
    FreeSketch(position2, pointer2);
}

private void FreeSketch(Point position2, Pointer pointer2)
{
    if (bDraw && pointer1.PointerId == pointer2.PointerId)
    {
        Line l = new Line()
        {
            X1 = position1.X,
            Y1 = position1.Y,
            X2 = position2.X,
            Y2 = position2.Y,
            StrokeThickness = 5,
            Stroke = new SolidColorBrush(Colors.Blue),
            Fill = new SolidColorBrush(Colors.Blue)
        };
        this.LayoutRoot.Children.Add(l); // adding to canvas
        this.position1 = position2;
    }
}

Happy coding

Search charm and user input gotchas #win8dev #winrtdev

A while back I implemented external and in-app search using search charm. This means that from anywhere in the app or even from main metro start screen, the user can start typing (which causes search to popup) and assuming they choose Cineworld, the search is passed off to my app.

Fast forward about 2 months back when I was implementing user submitted reviews for films and cinemas. I realised that the text input wouldn’t accept a single character – instead would keep showing the search charm….

aayyee.. that’s the search implementation… so I needed to selectively disable it depending upon where user is and what the user is up to.. trying to implement something meant going to layoutaware page so I don’t have to keep doing this.. whilst I was trying to figure out what to do next, I came across AllowSearch method.. strange.. then it occurred to me that I had added that while I was implementing search

 

protected void AllowSearch(bool bAllowed)
{
    SearchPane.GetForCurrentView().ShowOnKeyboardInput = bAllowed;
}

 
so I went about calling this.AllowSearch(false); in pages where I didn’t want search enabled.

Fast forward a bit closer, last week, I was using WebView allow ticket purchase in-app.. I tried clicks etc but not the full login etc as I know that already works and that’s implemented by Cineworld themselves.. I submit that app and a user contacts me saying.. they can’t book tickets.. search charm keeps popping up…

Damn it.. I had totally forgotten about AllowSearh method. Lets hope this serves as a reminder to myself to remember this in future.
Happy coding

WebView and working with C# and XAML #win8dev

Many of my Cineworld app users whether its Windows Phone or Windows 8 complain about lack of in-app ticketing. In fact I would personally as a user prefer otherwise – Use tried and trusted website for ticketing as opposed to an app – sure my app might be good enough to be an official app but that’s a different issue.

So what did I do, well for Windows Phone 7 and 8, I used WebBrowser control and added in-app use of Cineworld mobile website. Most users are happy – can’t please everyone. I do remember that WebBrowser control offered many more events for management in Windows Phone 8 than in Windows Phone 7. So how about Windows 8 ?

Well Windows 8 / WinRT 1.0 ships with WebView control. This is similar is many ways to Windows Phone 7 WebBrowser control. Why do I say that ? Well, it contains LoadCompleted event to inform about page loaded but no loading event. Doesn’t expose the internal navigation stack and is substantially more painful than Windows Phone 7 Browser Control :|

I am also aware that Windows 8.1 / WinRT 1.1 (??) ships with much improved WebView that exposes all the relevant event without hacks

Navigating Event: A quick search on the net found me Limitations of the WebView in Windows 8 Metro Apps. The post along side How to emulate Navigating event in the WebView turned out to be very useful. I used the WebViewWrapper to add Navigating event.

LoadCompleted Event: This event was exposed by the WebView and I used both maintain NavigationStack and toggle progress ring visibility

Progress Ring: Nothing can sit on top of WebView – no matter what order you define the elements in XAML. One needs to set WebView to collapsed visibility to show any other xaml content. I tend to toggle opacity to 0.5 and then show progress ring however this was a kill-joy till I found this “How to put a ProgressRing over a WebView” – easy peasy.. use WebViewBrush and paint a rectangle and hide the webview.. user cant really tell :)

Navigation Stack: Most pages in a Windows 8 apps expose back button. By default the back button calls GoBack defined in LayoutAwarePage.cs. It is however overrideable. So what should be behaviour be ? Well if you have been browsing a few pages, backbutton should ideally unwind that stack. Since WebView doesn’t really expose Nav Stack (just like Windows Phone 7 API), we need to do the dirty work. Use Completed to push the Uri. On Back button press pop the Uri. Apart from that, we just use InvokeScript to use browser’s internal nav stack using javascript.

<Grid Background="#FF231F20">
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="*"/>
    </Grid.RowDefinitions>

    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="Auto"/>
        <ColumnDefinition Width="*"/>
    </Grid.ColumnDefinitions>

    <WebView Grid.Row="0" Grid.RowSpan="2" Grid.Column="1" x:Name="wbCineworld" />
    <Rectangle Grid.Row="0" Grid.RowSpan="2" Grid.Column="1" Name="MaskRectangle"/>

    <Grid x:Name="gProgress" Grid.Row="0" Grid.RowSpan="2" Grid.Column="0" Grid.ColumnSpan="2" HorizontalAlignment="Stretch" VerticalAlignment="Center" Height="100" Background="White" Visibility="Collapsed">
        <ProgressRing x:Name="prProgress" HorizontalAlignment="Center" VerticalAlignment="Center" IsActive="True" Height="80" Width="80" Foreground="#FFB51C10"/>
    </Grid>

    <Button x:Name="backButton" Click="GoBack" IsEnabled="{Binding Frame.CanGoBack, ElementName=pageRoot}" Style="{StaticResource BackButtonStyle}"/>
    <Button Grid.Column="0" Grid.Row="1" VerticalAlignment="Bottom" x:Name="btnExitTicketing" Style="{StaticResource DeleteAppBarButtonStyle}" AutomationProperties.Name="Exit ticketing" Click="btnExitTicketing_Click" />
</Grid>
public sealed partial class InAppBrowser : Cineworld.Common.LayoutAwarePage
{
    public InAppBrowser()
    {
        this.InitializeComponent();

        var wrapper = new WebViewWrapper(this.wbCineworld);
        wrapper.Navigating += WrapperNavigating;
    }

    void WrapperNavigating(object sender, NavigatingEventArgs e)
    {
        this.SpinAndWait(true);
    }

    private Stack<Uri> NavigationStack = new Stack<Uri>();
    public static Uri NavigationUri { get; set; }

    private void SpinAndWait(bool bNewVal)
    {
        WebViewBrush brush = new WebViewBrush();
        brush.SourceName = "wbCineworld";
        brush.Redraw();
        MaskRectangle.Fill = brush;

        this.wbCineworld.Visibility = bNewVal ? Windows.UI.Xaml.Visibility.Collapsed : Windows.UI.Xaml.Visibility.Visible;
        this.MaskRectangle.Opacity = bNewVal ? 0.5 : 1;

        this.MaskRectangle.Visibility = bNewVal ? Windows.UI.Xaml.Visibility.Visible : Windows.UI.Xaml.Visibility.Collapsed;

        this.gProgress.Visibility = bNewVal ? Windows.UI.Xaml.Visibility.Visible : Windows.UI.Xaml.Visibility.Collapsed;
        this.prProgress.IsActive = bNewVal;
    }

    protected override void OnNavigatedTo(NavigationEventArgs e)
    {
        base.OnNavigatedTo(e);

        this.wbCineworld.LoadCompleted += wbCineworld_LoadCompleted;

        this.wbCineworld.Navigate(NavigationUri);

        this.SpinAndWait(true);
    }

    void wbCineworld_LoadCompleted(object sender, NavigationEventArgs e)
    {
        this.SpinAndWait(false);
        NavigationStack.Push(e.Uri);
    }

    protected override void GoBack(object sender, RoutedEventArgs e)
    {
        if (this.NavigationStack.Count > 1)
        {
            this.wbCineworld.InvokeScript("eval", new string[1] { "history.go(-1)" });

            // note that this is another Pop - as when the navigate occurs a Push() will happen
            NavigationStack.Pop();
        }
        else
            base.GoBack(sender, e);
    }

    private void btnExitTicketing_Click(object sender, RoutedEventArgs e)
    {
        base.GoBack(sender, e);
    }
}

Let me just reiterate – I haven’t found something new, I have just found a few bits and have put them together. Happy coding.

Note: Meant to post this earlier.. I am checking NavigationStack.Count and ideally the check should be > 0 but in my case, there was an additional redirection and hence I am using Count > 1.

Persistent Thread like behavior with #win8dev

As you might have gathered, I
* like writing bad code
* doing things that people frown upon (like writing bad code)

Ever since I started Windows 8 Development, I miss Threads in all their glory. Sure Async Task is mostly fine but its not the same. Earlier today, Arafat asked a question about truly async logging mechanism. I suggested hacking Async Task into a thread like behaviour :) – actually it just gets you a threadpool thread :)

Task.Run provides a mechanism to queue given code on a ThreadPool for parallel execution. What happens when you refuse to return the method ? well you get the ThreadPool thread as your personal bitch :)

CancellationTokenSource CancellationSource = null;
CancellationToken TaskCancellationToken;

private async void AlwaysOnLoggingAsyncTask()
{
     while (!this.TaskCancellationToken.IsCancellationRequested)
     {
          // do something.. actually do anything
          // in the sample I was mucking around with StorageFile
          // hence the async void 

          await Task.Delay(1000); // don't kill the PC by running a tight loop.
     }
}

private async void btnStart_Click(object sender, RoutedEventArgs e)
{
     CancellationSource = new CancellationTokenSource();
     this.TaskCancellationToken = CancellationSource.Token;
     Task.Run(() => this.AlwaysOnLoggingAsyncTask(), TaskCancellationToken);
}

private void btnStop_Click(object sender, RoutedEventArgs e)
{
     CancellationSource.Cancel();
}

Here’s a dummy sample logging project that incorporates this bad code :)

Update: since I was writing really bad code, I deliberately forgot to add Task.Delay. If you prefer to not write code that makes system a bit less miserable, consider adding a Task.Delay of about 1000 (1 second)

Update 2: Jarno pointed out that I am writing really really bad code – mechanism dating pre-Task era – which is correct. Old habits die hard. Well I’ve update the blog plus source :P to use Task Cancellation Token

Converter to toggle visibility when content is empty #wpdev #wp8dev #wp7dev #win8dev

Recently Gustavo Guerra posted a question on StackOverflow.com stating that behaviour of TextBlock was different on Windows Phone 7 and Windows Phone 8. If the Text is empty, WP7 renders TextBlock with Height set to 0. On WP8, it occupies full height.

I replied back stating that he should consider using a Converter for the same. Of course I had a similar issue with Cineworld app. The screenshot shows ratings & review screen I implemented – its almost a copy of Windows Phone Store ratings & review.
wp_ss_20130704_0002[1]

what I noticed was that if user chose to not review it, the textbox would be fully render. So I did what I suggested Gustavo do. Created two converters – StringLengthInvisibilityConverter and StringLengthVisibilityConverter. Almost identical but doing the opposite thing.

 

public class StringLengthInvisibilityConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        string itemVal = value as String;
        if (String.IsNullOrWhiteSpace(itemVal))
            return Visibility.Collapsed;
        else
            return Visibility.Visible;
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

public class StringLengthVisibilityConverter : IValueConverter
{

    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        string itemVal = value as String;
        if (String.IsNullOrWhiteSpace(itemVal))
            return Visibility.Visible;
        else
            return Visibility.Collapsed;
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}
<TextBlock Text="{Binding Review}" Visibility="{Binding Review, Converter={StaticResource InvisibilityConverter}}" TextWrapping="Wrap" Style="{StaticResource PhoneTextNormalStyle}" Grid.Column="0" Grid.Row="1" Grid.ColumnSpan="2"/>
<TextBlock Text="(rating only)" Visibility="{Binding Review, Converter={StaticResource VisibilityConverter}}" Foreground="{StaticResource PhoneSubtleBrush}" TextWrapping="Wrap" Style="{StaticResource PhoneTextNormalStyle}" Grid.Column="0" Grid.Row="1" Grid.ColumnSpan="2"/>

 

Now I know one of you clever person is going to tell me I could have just used one :P Let me tell you this:

  1. I thought of it
  2. I could have searched around
  3. Realised no one really cares
  4. Created two converters and got the job done :)
  5. Submitted update and nap time

.