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

.

Semantic zoom – beyond the stock behaviour – #windev #winrt

Update: Download a sample implementation from skydrive

Last year I was working on Cineworld app for Windows 8. Having use LongListSelector I wanted to ensure that I can transfer the look and feel. However I was fighting multiple battles – the first one is that while LongListSelector is a single control, SemanticZoom control itself contains ZoomInView and ZoomedOutView. These are independent of each other and most examples then to show settings data to zoomed in view and then zoomed out view referring to zoomed in view. It gets messy – maybe I am just slow but it was not intuitive and took me ages.

While mucking around, I came across this post and from there, kept trying till I got what I wanted.

LLS1LLS 

Screenshot (220)

Screenshot (221)

 

<Page.Resources>
    <CollectionViewSource x:Name="cvsFilms" IsSourceGrouped="true" />

    <!-- Zoomed out templates and selectors -->
    <DataTemplate x:Key="GroupTemplate">
        <Border Margin="6" Width="75" Height="75" Background="Black" >
            <TextBlock Text="{Binding Name}" Foreground="White" FontSize="32" FontWeight="Bold" HorizontalAlignment="Center" VerticalAlignment="Center" />
        </Border>
    </DataTemplate>
    <DataTemplate x:Key="EmptyGroupTemplate">
        <Border Margin="6" Width="75" Height="75" BorderBrush="Black" BorderThickness="1" Background="LightGray">
            <TextBlock Text="{Binding Name}" Foreground="Black" FontSize="32" FontWeight="Bold" HorizontalAlignment="Center" VerticalAlignment="Center" />
        </Border>
    </DataTemplate>
    <local:EmptyOrFullSelector
            x:Key="FilmGroupEmptyOrFullSelector"
            Empty="{StaticResource EmptyGroupTemplate}"
            Full="{StaticResource GroupTemplate}" />
    <DataTemplate x:Key="GroupHeaderTemplate">
        <Border Margin="20, 20, 0, 0" Width="75" Height="75" Background="Black" Tapped="Grid_Tapped">
            <TextBlock Text="{Binding Key}" Foreground="White" FontSize="32" FontWeight="Bold" HorizontalAlignment="Center" VerticalAlignment="Center" />
        </Border>
    </DataTemplate>
    <DataTemplate x:Key="GroupItemTemplate">
        <Border Margin="14, 20, 0, 0">
            <Grid Height="350" Width="185" Margin="0">
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto" />
                    <RowDefinition Height="*" />
                </Grid.RowDefinitions>
                <Image  Source="{Binding PosterUrl}" Height="278" Width="185" VerticalAlignment="Top" HorizontalAlignment="Left" Stretch="UniformToFill"/>
                <TextBlock Grid.Row="1" TextWrapping="Wrap" VerticalAlignment="Top" Text="{Binding Title}" HorizontalAlignment="Center" FontFamily="Segoe UI" />
            </Grid>
        </Border>
    </DataTemplate>
</Page.Resources>

<SemanticZoom x:Name="semanticZoom" Background="White" HorizontalAlignment="Stretch" Grid.Row="1" VerticalAlignment="Stretch">
    <SemanticZoom.ZoomedOutView>
        <GridView ScrollViewer.IsHorizontalScrollChainingEnabled="False" HorizontalAlignment="Center" ItemTemplateSelector="{StaticResource FilmGroupEmptyOrFullSelector}" >
            <GridView.ItemsPanel>
                <ItemsPanelTemplate>
                    <WrapGrid Background="LightGray" MaximumRowsOrColumns="9" VerticalChildrenAlignment="Center" Orientation="Horizontal"/>
                </ItemsPanelTemplate>
            </GridView.ItemsPanel>
        </GridView>
    </SemanticZoom.ZoomedOutView>
    <SemanticZoom.ZoomedInView>
        <GridView x:Name="gvZoomedInFilms" ItemsSource="{Binding Source={StaticResource cvsFilms}}" IsSwipeEnabled="True" ScrollViewer.IsHorizontalScrollChainingEnabled="False" ItemTemplate="{StaticResource GroupItemTemplate}">
            <GridView.ItemsPanel>
                <ItemsPanelTemplate>
                    <VirtualizingStackPanel Orientation="Horizontal"/>
                </ItemsPanelTemplate>
            </GridView.ItemsPanel>
            <GridView.GroupStyle>
                <GroupStyle HeaderTemplate="{StaticResource GroupHeaderTemplate}">
                    <GroupStyle.Panel>
                        <ItemsPanelTemplate>
                            <VariableSizedWrapGrid Orientation="Vertical" Margin="0,0,50,0"/>
                        </ItemsPanelTemplate>
                    </GroupStyle.Panel>
                </GroupStyle>
            </GridView.GroupStyle>
        </GridView>
    </SemanticZoom.ZoomedInView>
</SemanticZoom>
List<GroupInfoList<object>> dataLetter = null;

public ListFilms()
{
    this.InitializeComponent();

    FilmData cd = new FilmData(App.Films);

    dataLetter = cd.GroupsByLetter; 
    cvsFilms.Source = dataLetter;
    gvZoomedInFilms.SelectionChanged -= gvZoomedIn_SelectionChanged;
    gvZoomedInFilms.SelectedItem = null;
    (semanticZoom.ZoomedOutView as ListViewBase).ItemsSource = cd.FilmHeaders;     gvZoomedInFilms.SelectionChanged += gvZoomedIn_SelectionChanged;

    semanticZoom.ViewChangeStarted -= semanticZoom_ViewChangeStarted;
    semanticZoom.ViewChangeStarted += semanticZoom_ViewChangeStarted;
}

void semanticZoom_ViewChangeStarted(object sender, SemanticZoomViewChangedEventArgs e)
{
    if (e.SourceItem == null)
        return;

    if (e.SourceItem.Item.GetType() == typeof(HeaderItem))
    {
        HeaderItem hi = (HeaderItem)e.SourceItem.Item;

        var group = dataLetter.Find(d => ((char)d.Key) == hi.Name);
        if (group != null)
            e.DestinationItem = new SemanticZoomLocation() { Item = group };
    }
}

// FilmData looks like this
private List<GroupInfoList<object>> groupsByLetter = null;

public List<GroupInfoList<object>> GroupsByLetter
{
    get
    {
        if (groupsByLetter == null)
        {
            groupsByLetter = new List<GroupInfoList<object>>();

            var query = from item in Collection
                        orderby ((FilmInfo)item).Title
                        group item by ((FilmInfo)item).HeaderChar into g
                        select new { GroupName = g.Key, Items = g };

            foreach (var g in query)
            {
                GroupInfoList<object> info = new GroupInfoList<object>();
                info.Key = g.GroupName;
                foreach (var item in g.Items)
                {
                    info.Add(item);
                }
                groupsByLetter.Add(info);
            }
        }

        return groupsByLetter;
    }
}

List<HeaderItem> filmHeaders = null;
public List<HeaderItem> FilmHeaders
{
    get
    {
        if (filmHeaders == null)
        {
            filmHeaders = new List<HeaderItem>();

            char c = '#';

            filmHeaders.Add(new HeaderItem() { Name = '#', IsEnabled = this.GroupsByLetter.Exists(k => ((char)k.Key) == c) });
                    
            for (int i = 65; i <= 90; i++)
            {
                c = (char)i;

                if (this.GroupsByLetter.Exists(k => ((char)k.Key) == c))
                    filmHeaders.Add(new HeaderItem() { Name = c, IsEnabled = true });
                else
                    filmHeaders.Add(new HeaderItem() { Name = c, IsEnabled = false });
            }                    
         }

        return filmHeaders;
    }
}

I think that’s about it. Its been 6 months now and I think I am going to change how it looks :) some stuff will remain as it is, others will have to change

Geolocator and MovementThreshold #wpdev #win8dev

Last few months, I have had too much on my plate. Been doing lot to Windows 8 and Phone development. Surprisingly Microsoft UK is keeping tabs on phone developers who aren’t adapting to #WP8 and seemingly, I was invited to a dev event targeting the likes of me :P

Sure I am going and in anticipation of the event, I decided to port Cineworld app to WP8. Its been a challenging task. Reworking a few bits of LongListSelector, Visual Studio / Blend disliking all the xaml and of course a button style causing xaml exception. If that wasn’t enough:

Having used Geolocator in Windows 8 app, I decided to use the same for WP8 as its usually a lot faster than GeoCoordinateWatcher. I moved the code to be more like Win8 and noticed that the location detection was flaky at best. Now I did the stupid thing and like in WP7 version, I decided to set both DesiredAccuracy to High and MovementThreshold to 0 thinking absolutely nothing.

Of course that didn’t help it, it made matters worse, instead of flaky behaviour, it decided to call it quits.

var pos = await locator.GetGeopositionAsync(TimeSpan.FromMinutes(5), TimeSpan.FromSeconds(2));

instead of timing out, it started to hang. In desperation, I started looking at other events exposed by this class and tried hooking into StatusChanged event. Now things were bad, I noticed that it was getting operation aborted exception and decided that something was seriously wrong and that I should take a nap instead :)

Of course the problem was still there when I woke up the next day :P its only later that I decided to search on Geolocation and operation aborted and realised that I wasn’t the only one and it was all my fault – causality of me setting the MovementThreshold to 0. I set it to 10 instead and bingo.. it all works.

While I didn’t find it, I hope this post helps people like an earlier post helped me.