Help the DVLUP Challenge: Go ahead, rate my app!

The DVLUP program has an interesting challenge: Go ahead, rate my app!

This challenge wants your app to encourage feedback. Yeah just feedback, similar to an article I wrote about a year ago for Windows Style apps. The interesting thing is that you don’t have to do that much. The challenge already contains code you can copy/paste.

But wait, there’s more, of course we want the words and sentences that appear in the dialogs to be localized, don’t we? I would love to add this to my P | Cast app. But my app is localized in a lot of different languages.

So please join me and help improve the Helperslib project, based on the code that’s provided by DVLUP, improved and made available on NuGet by @SimonDarksideJ. I already added Dutch to the Git Repository. Why don’t you add your native languages?

Development made easier for Apps that need some setup

Some of the apps I had didn’t need much setup, but some of them did. For example in my the Podcast app I created, P | Cast, I need to have some subscriptions and downloaded tracks. You of course don’t want to search for podcasts, add as subscription and wait for the tracks to download before you can continue to test/dev.

You are lucky, right away! I wasn’t until two weeks ago, when I discovered the following way of working.

Step 1 – Install the Isolated Storage Explorer

First be prepared and install the Visual Studio 2012 add in called: Isolated Storage Explorer. This will enable easy access to the Isolated Storage of your Emulator or actual Device for the app your developing. After installation you can find the Isolated Storage Explorer in the View menu.

Step 2 – Run your app and setup data

Now run your app, either on the Emulator or on your physical device. Make sure to setup all data. In my case I did search for some podcasts and subscribed to them. I also waited to make sure the podcast files were all downloaded completely. Make sure to shut down your app, and stop debugging.

Step 3 – Backup your isolated storage

To backup your isolated storage open the Isolated Storage Explorer, if you don’t have it visible you can find it in the View menu of Visual Studio. Then pick the button with the arrow pointing downwards to Take a Snapshot of the Isolated Storage and pick a folder where you want to save the Snapshot.

image

Restore your Isolated Storage

So now you’re prepared, if you restart your emulator or for some reason the app can’t be just updated on your phone and get’s a fresh install. Do the following.

Run your app and shut it down, to make sure that no Isolated Storage Files are locked.

Again make sure you have the Isolated Storage Explorer open and pick the button with the arrow pointing upwards to Restore a Snapshot and pick the folder you’ve used before to save the Snapshot.

When you now start your app, you will see that the Isolated Storage is restored. Hope you enjoy creating apps even more.

image

Don’t make your Application lifetime events async void!

So just to rephrase: Don’t make your Application lifetime events async void!

Yes, I learned the hard way. Yes I’ve read, and know, about the: Never make a void async. But if you want write an event-handler you’ve got no choice. But beware, sometimes things look to be working okay, but actually don’t.

Alright, back to where all my trouble started. Every Windows Phone App developer knows about the Application Lifetime events that are automatically subscribed to in the App.xaml.cs. You’ve probably added code to at least one of the following event-handlers.

Application_Launching: Occurs when the application is being launched

Application_Closing: Occurs when the application is exiting

Application_Activated: Occurs when the application is being made active after previously being put into a dormant state or tombstoned.

Application_Deactivated: Occurs when the application is being deactivated. You have 10 seconds to complete your work, though it’s recommended to aim for completing the work within 2 seconds.

No await in those event handlers!

Alright, I’m just writing code. I need to perform the last small SQLite query to save some state. Hmm, that’s done in the Closing method. I’m writing the code, oh yeah, the SQLite query is an asynchronous operation. I write await, hmm, mark the method as async void. Hmm, shouldn’t do that, should I? It’s an event-handler, true, but don’t forget you’ve done it before, and the code does execute. Okay move on and test later. I’ll be honest, I forgot to test, but I got some strange issues that I had difficulty with solving.

What I found out, that as soon as the word await was hit in the event-handler, the thread was given back to the application, which kind of signaled the app, I’m ready to terminate. Ouch! The actual never executed, that was painful! Just note, after save the settings in the SQLite database, I did the closing of all open connections. This closing never happened either, which in itself caused strange situations with trying to execute queries on closed connections when the app resumed.

Okay I learned the hard way, don’t use await in the above mentioned event-handlers, better don’t use it in any event-handler.

But I need that API call, which happens to be async

So I started looking for a way to call a Task synchronously. Yes I found a way on StackOverflow that works very well. So I could change my code like this, which indeed does result in nice code I think.

private void Application_Closing(object sender, ClosingEventArgs e)
{
    Debug.WriteLine("BEGIN - ApplicationClosing");
    AsyncHelpers.RunSync(() => ApplicationClosingAsync(sender, e));
    Debug.WriteLine("END - ApplicationClosing");
}

private async Task ApplicationClosingAsync(object sender, ClosingEventArgs e)
{
    try
    {
        ApplicationSettings settings = await ApplicationSettings.LoadSettings();
        settings.LastAppRun = DateTime.Now;
        await ApplicationSettings.SaveSettings(settings);
        ViewModelLocator.Cleanup();
        SQLiteConnectionPool.Shared.ApplicationSuspended();
    }
    catch (Exception exception)
    {
        //swallow exceptions that occur at this moment.
    }
}

 

All the code that was originally in the Application_Closing event handler is now moved to the ApplicationClosingAsync method, which indeed is an async method which returns a Task. The method contains multiple await statements, the keyword that shouldn’t be in de event handler itself. I added the Debug information for testing purpose, so you can see everything get’s called. The magic is in the AsyncHelper method which I copied from the StackOverflow site, so please place the credits in the right place. I’ve shown the code for Application_Closing, but it works for the other event-handlers as well.

UPDATE 1: According to Oren Novotny this feature also exists in the Nito.AsyncEx NuGet Package. Pick the one you like best, but at least test your code.

public static class AsyncHelpers
{
    /// <summary>
    /// Execute's an async Task method which has a void return value synchronously
    /// </summary>
    /// <param name="task">Task method to execute</param>
    public static void RunSync(Func<Task> task)
    {
        var oldContext = SynchronizationContext.Current;
        var synch = new ExclusiveSynchronizationContext();
        SynchronizationContext.SetSynchronizationContext(synch);
        synch.Post(async _ =>
        {
            try
            {
                await task();
            }
            catch (Exception e)
            {
                synch.InnerException = e;
                throw;
            }
            finally
            {
                synch.EndMessageLoop();
            }
        }, null);
        synch.BeginMessageLoop();

        SynchronizationContext.SetSynchronizationContext(oldContext);
    }

    /// <summary>
    /// Execute's an async Task<T> method which has a T return type synchronously
    /// </summary>
    /// <typeparam name="T">Return Type</typeparam>
    /// <param name="task">Task<T> method to execute</param>
    /// <returns></returns>
    public static T RunSync<T>(Func<Task<T>> task)
    {
        var oldContext = SynchronizationContext.Current;
        var synch = new ExclusiveSynchronizationContext();
        SynchronizationContext.SetSynchronizationContext(synch);
        T ret = default(T);
        synch.Post(async _ =>
        {
            try
            {
                ret = await task();
            }
            catch (Exception e)
            {
                synch.InnerException = e;
                throw;
            }
            finally
            {
                synch.EndMessageLoop();
            }
        }, null);
        synch.BeginMessageLoop();
        SynchronizationContext.SetSynchronizationContext(oldContext);
        return ret;
    }

    private class ExclusiveSynchronizationContext : SynchronizationContext
    {
        private bool done;
        public Exception InnerException { get; set; }
        readonly AutoResetEvent workItemsWaiting = new AutoResetEvent(false);
        readonly Queue<Tuple<SendOrPostCallback, object>> items =
            new Queue<Tuple<SendOrPostCallback, object>>();

        public override void Send(SendOrPostCallback d, object state)
        {
            throw new NotSupportedException("We cannot send to our same thread");
        }

        public override void Post(SendOrPostCallback d, object state)
        {
            lock (items)
            {
                items.Enqueue(Tuple.Create(d, state));
            }
            workItemsWaiting.Set();
        }

        public void EndMessageLoop()
        {
            Post(_ => done = true, null);
        }

        public void BeginMessageLoop()
        {
            while (!done)
            {
                Tuple<SendOrPostCallback, object> task = null;
                lock (items)
                {
                    if (items.Count > 0)
                    {
                        task = items.Dequeue();
                    }
                }
                if (task != null)
                {
                    task.Item1(task.Item2);
                    if (InnerException != null) // the method threw an exeption
                    {
                        throw new AggregateException("AsyncHelpers.Run method threw an exception.", InnerException);
                    }
                }
                else
                {
                    workItemsWaiting.WaitOne();
                }
            }
        }

        public override SynchronizationContext CreateCopy()
        {
            return this;
        }
    }
}

Make the ListPicker or RadListPicker behave in a ScrollViewer

I’ve seen a lot of applications that have a page in there that just doesn’t behave the way it should. Either there’s a textbox that’s placed in a not so brilliant way, where a lot of controls are covered by the onscreen keyboard and there’s not a nice way to close the keyboard (tapping somewhere on the screen is not a nice way, is it?). The same goes for ListPickers, when they are placed in a ScrollViewer at the bottom of the screen chances are that you’re only seeing one item once you open de ListPicker, the rest is at the bottom of the screen.

A picture is worth a thousand words, so here the situation of the ListPicker I’m explaining, closed (no trouble) and opened where the user hardly sees that there are options at all.

closed

opened wrong

 

 

 

 

 

 

 

 

Of course I want to fix this. And I even know I fixed this before, but I had to think hard in which app I fixed this problem. I found the code but in the old app I was making use of the ListPicker from the Windows Phone Toolkit and now I’m making use of the RadListPicker by Telerik. Though besides that I didn’t find anyone blogging about this before. That’s why I’m writing this. The code I show in here could have been written by someone else, but I can’t remember.

ListPicker from the Windows Phone Toolkit solution

The original ListPicker can react to the GotFocus event to then bind to the SizeChanged event in which the actual logic for making the control visible in the scrollviewer is called. The magic piece is shown in the end, it’s shared by both solutions. The magic is in line 8 of course.

NewTracksToDownloadPicker.GotFocus += PickerGotFocus;

private void PickerGotFocus(object sender, RoutedEventArgs eventArgs)
{
    var picker = sender as ListPicker;
    if (picker != null)
    {
        picker.SizeChanged += (s, e) => picker.EnsureVisibleInScrollViewer();
    }
}

RadListPicker by Telerik solution

The RadListPicker by Telerik doesn’t fire the GotFocus event at the same time, so I had to pick and try to correct event to listen to. I found out that the StateChanged event works best for me.

NewTracksToDownloadPicker.StateChanged += PickerStateChanged;

private void PickerStateChanged(object sender, ListPickerStateChangedEventArgs listPickerStateChangedEventArgs)
{
    var picker = sender as RadListPicker;
    if (picker != null)
    {
        picker.SizeChanged += (s, e) => picker.EnsureVisibleInScrollViewer();
    }
}

 

So now it’s time for some magic!

No not really, but the code can be quite handy for other situations as well when you want to be sure a control is completely visible inside a ScrollViewer.

The magic consists of two parts, finding the parent ScrollViewer of the Control you want to make visible. With all kinds of nesting, it could be difficult to tell how many levels are there. So with the help of the VisualTreeHelper and a little bit of recursion you get this pieces of code.

public static T FindParentOf<T>(this UIElement element) where T : UIElement
{
    var found = FindParentOf(element, typeof(T)) as T;
    return found;
}

public static DependencyObject FindParentOf(DependencyObject element, Type type)
{
    if (type.IsInstanceOfType(element))
        return element;
    DependencyObject parent = VisualTreeHelper.GetParent(element);
    if (parent == null)
        return null;
    return FindParentOf(parent, type);
}

 

So that piece of magic is gone. Next is the actual making sure that the control is visible in the ScrollViewer. A little bit of measuring and making the ScrollViewer to scroll to the measured position. What magic were you talking about?

public static void EnsureVisible(this ScrollViewer scroller, UIElement element)
{
    scroller.UpdateLayout();

    double maxScrollPos = scroller.ExtentHeight - scroller.ViewportHeight;
    double scrollPos =
        scroller.VerticalOffset -
        scroller.TransformToVisual(element).Transform(new Point(0, 0)).Y;

    if (scrollPos > maxScrollPos) scrollPos = maxScrollPos;
    else if (scrollPos < 0) scrollPos = 0;

    scroller.ScrollToVerticalOffset(scrollPos);
}

public static void EnsureVisibleInScrollViewer(this UIElement element)
{
    var scrollViewer = element.FindParentOf<ScrollViewer>();
    if (scrollViewer != null)
        scrollViewer.EnsureVisible(element);
}

 

Yes, I know you want to see the end result. Have fun with it!

opened correctly

Starting a BackgroundTransfer from your Background Agent

Alright, I thought I had a valid reason to start a BackgroundTransfer from my Background Agent. Sadly it doesn’t work. After a small discussion with Ilija Injac he pointed me to Unsupported APIs for Background Agents page on MSDN. Though when trying to find something based on the Exception I couldn’t find anything.

The message I got was: Operation is not valid due to the current state of the object.

With the following StackTrace:

   at Microsoft.Phone.BackgroundTransfer.BackgroundTransferRequest.SubmitHelper()
   at Microsoft.Phone.BackgroundTransfer.BackgroundTransferRequest.Submit()
   at Microsoft.Phone.BackgroundTransfer.BackgroundTransferService.Add(BackgroundTransferRequest request)
   at MC.PodCast.Common.Services.Download.DownloadService.Enqueue(Boolean eventLess)
   at MC.PodCast.Common.Services.Download.DownloadService.<Start>d__5.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
   at MC.PodCast.TaskAgent.ScheduledAgent.<<OnInvoke>b__3>d__4.MoveNext()

 

Hope this helps when you get an exception like the above. It’s just not supported to start a BackgroundTransfer from a Background Agent. Better luck next time.