Skip to content
/

The other day I was working on a Windows Phone app. I wanted to add a “pull down to refresh” panel to a large list of images. Just like the Facebook and Twitter apps have.

Pull-to-refresh in the Twitter app animation. Showing a text to encourage the user pull down further to refresh the list. When pulled down far enough the text changes to let the user know the list will be refreshed after the user releases his finger from the screen.

Pull-to-refresh in the Twitter app. Image by David Washington

As Microsoft does not provide this functionality in their default controls I started searching the web if somebody else has build something like this already.
I found a blog post by Jason Ginchereau where he provided this functionality for Windows Phone 7.
In my app I use an ItemsControl with a VirtualizingStackPanel to prevent memory issues. After I added the PullDownToRefreshPanel control to my list and started testing it on my phone, I ran into some issues.

The issues

Adding the control to my page was easy. But I noticed two things.

  1. Performance, it’s taking up a lot of processing power, resulting in visual lag. Specially when using a low powered phone.
  2. Scrolling, when scrolling through the list with a quick flicking motion the same images kept scrolling by, making the list scroll endlessly until I stopped flicking

In this blog post I will describe my contributions to fix these 2 issues and I will supply the source code for you to use.

1. Improving performance

Looking at the code, the first thing I noticed was that the control subscribes to the LayoutUpdated event. The code in the event handler tries to find the ScrollViewer control to attach to. After the ScrollViewer is successfully found, the event is never unsubscribed and keeps firing quite often. When you add a debug message to the method you’ll see the event fires constantly during the actual scrolling, but also fires when the control is not even on the screen. So the first fix was to unregister the event if the ScrollViewer is found. There is no need to fire unnecessary code.

private void PullDownToRefreshPanel_LayoutUpdated(object sender, EventArgs e)
{
    if (this.targetScrollViewer == null)
    {
        this.targetScrollViewer = 
             FindVisualElement<ScrollViewer>(VisualTreeHelper.GetParent(this));
        if (this.targetScrollViewer != null)
        {
            this.LayoutUpdated -= PullDownToRefreshPanel_LayoutUpdated;
            // *snip*
        }
    }
}

The second thing I observed were the NegativeValueConverters. The ValueConvertor adds negative space at the bottom to keep the ScrollViewer positioned on the same location if the PullDownToRefreshPanel was growing in height.
Inside the convertor there is an unnecessary Convert from Object to Double. When resizing the control this conversion was called a lot of times. So this could be written a bit simpler as the value is already of the type Double.

//double doubleValue = -System.Convert.ToDouble(value);
double doubleValue = -(double)value; // No System.Convert needed

When looking at the original example project by Jason, the negative space was needed because the control and the list are in separate rows in a grid. By changing the XAML to put both controls in the same grid cell there is no need for this negative space because the controls are now floating on top of each other. Eliminating the ValueConvertors all together made the process much lighter.
My XAML looks a bit like this:

<Grid>
  <rlb:PullDownToRefreshPanel x:Name="refreshPanel"
                              RefreshRequested="refreshPanel_RefreshRequested" 
                              VerticalAlignment="Top" />
  <ItemsControl x:Name="listBox"
                ItemsSource="{Binding}">
      <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
          <VirtualizingStackPanel Orientation="Vertical" />
        </ItemsPanelTemplate>
      </ItemsControl.ItemsPanel>
      <ItemsControl.Template>
        <ControlTemplate TargetType="ItemsControl">
          <ScrollViewer ManipulationMode="Control">
            <ItemsPresenter/>
          </ScrollViewer>
        </ControlTemplate>
    </ItemsControl.Template>
  </ItemsControl>
</Grid>

2. Fixing the scrolling

To make the pull-to-refresh list work, it’s mandatory to change the ManipulationMode property of the ScrollViewer to “Control“. This allows you to catch the MouseMove event and the MouseLeftButtonUp event. With these events you can detect the change of the position of the content inside the ScrollViewer by monitoring the TranslateY property which changes when the compression happens.

Because I noticed the same images kept scrolling by, I was suspecting the VirtualizingStackPanel was not receiving the correct signals and was recycling the same placeholders (and images) over and over without getting fresh data as it should.
Searching the web again I came across a blog post by Matthijs Krempel describing that the Mango update added some new candy that would allow you to detect the compression using VisualStates and therefore you can leave the ManipulationMode on “System”. Resulting in a better performance and in a correctly functioning VirtualizingStackPanel. This does not work out-of-the-box, you need to add a specific template to the ScrollViewer.
Matthijs added this to his own “PullToRefreshPanel” control.

However, the VisualStates let you only know if compression has started or ended. It doesn’t let you know how much compression is applied. Without the mouse events I needed another way to detect the amount of compression. Which led me to build my own version of the control.

Building a new Pull-Down-To-Refresh Panel

Windows Phone provides the Touch class which is an application-level service that processes touch input from the operating system and raises the FrameReported event. Inside this event you can read what kind of interaction is happening between the fingers and the screen.

private void TouchFrameReported(object sender, TouchFrameEventArgs e)
{
    var primaryTouchPoint = e.GetPrimaryTouchPoint(this);

    switch (primaryTouchPoint.Action)
    {
        case TouchAction.Down:
            this.initialPoint = primaryTouchPoint.Position;

            if (this.isCompressed)
            {
                this.StartMeasuring();
            }

            break;

        case TouchAction.Move:
            if (this.isMeasuring)
            {
                // Only update if the finger moves up/down the screen
                if (this.currentPosition.Y != primaryTouchPoint.Position.Y)
                {
                    this.currentPosition = primaryTouchPoint.Position;
                    this.UpdateControl();
                }
            }
            else
            {
                this.initialPoint = primaryTouchPoint.Position;
            }

            break;

        case TouchAction.Up:
            this.StopMeasuring();

            break;
    }
}

So I combined the control Jason originally wrote with the extensions Matthijs made to detect compression. Then I replaced the mouse events with touch actions. Resulting in a faster control that also works with virtualized controls like an ItemsControl with a VirtualizingStackPanel or the ListBox.

I’ll have to note that the PullDownToRefreshPanel control will not work with the LongListSelector as that control does not expose a ScrollViewer.

Source code

You can download my Windows Phone 8 example project on GitHub.

/

With Windows Azure we can use Windows Azure SQL Database service (formerly known as SQL Azure) when we need a Relational Database. Microsoft offers a 99.9% monthly SLA for this service. But Microsoft doesn’t provide you with the service to restore your data to a moment back in time when you (accidentally) delete of corrupt data.

With an “on premise” Microsoft SQL Server installation you would solve this by configuring and scheduling (transactional log) backups. But this isn’t possible for the Windows Azure service.

You could replicate a copy of your database using SQL Data Sync with a delay. But if you fail to discover the issue in time for the next scheduled sync your copy won’t make a difference.

To have a backup in time I wrote some code to allow a Worker Role to backup my Windows Azure SQL Database every hour. Most solutions you find online are relying on the REST Endpoints but the address of the endpoint is different depending on which datacenter your database is hosted. I found a different solution where you only need the connection string to your database using the DacServices.

Pre-requisites

To make a backup I use the Microsoft SQL Server 2012 Data-Tier Application Framework. This framework provides the DacServices Class.

You need to configure Local Storage to store the backup temporary and you need a Storage Account to store the backup file permanently.

The solution

// Get the Storage Account
var backupStorageAccount = 
                CloudStorageAccount.FromConfigurationSetting("StorageAccount");

// The container to store backups
var backupBlobClient = backupStorageAccount.CreateCloudBlobClient();
backupContainer = backupBlobClient.GetContainerReference("backups");
backupContainer.CreateIfNotExist();

// The backup file on blob storage
var storageName = 
  string.Format("Backup_{0}.bacpac", DateTime.Now.ToString("yyyyMMdd-HHmmss"));
var backupFile = backupContainer.GetBlobReference(storageName);

// Get a reference to the temporary files
var localResource = RoleEnvironment.GetLocalResource("TempFiles");
var file = string.Format("{0}{1}", localResource.RootPath, backupFile.Name);

// Connect to the DacServices
var services = new DacServices(ConfigurationManager
                          .ConnectionStrings["DatabaseName"].ConnectionString);
services.Message += (sender, e) =>
    {
        // If you use a lock file, 
        // this would be a good location to extend the lease
    };

// Export the database to the local disc
services.ExportBacpac(file, "DatabaseName");

// Upload the file to Blob Storage
backupFile.Properties.ContentType = "binary/octet-stream";
backupFile.UploadFile(file);

// Remove the temporary file
File.Delete(file);

Explanation

The code does the following:

  1. Connect to the Storage Account
  2. Get a reference to the container and file where you want to store the backup
  3. Get a reference to the local storage location
  4. Connect to the DacService using the database connection string
  5. Export the database to a “.bacpac” file
  6. Upload the file to blob storage
  7. Delete the local file

A Catch

Before you deploy your Worker Role you’ll have to make sure each of the listed assemblies are referenced and the property “Copy Local” is set to “True” otherwise you will run into trouble.

  • Microsoft.Data.Tools.Schema.Sql
  • Microsoft.Data.Tools.Utilities
  • Microsoft.SqlServer.Dac
  • Microsoft.SqlServer.TransactSql
  • Microsoft.SqlServer.TransactSql.ScriptDom
  • Microsoft.SqlServer.Types
/

Techdays 2013 Netherlands

I’m invited to speak at the in the Netherlands. The event is held on the & of March at the World Forum in Den Haag

My session, in Dutch, is called “” and I will be talking about my experiences using Windows Azure to build a high available and scaling platform for the various applications used during “3FM Serious Request“, the annual charity event organized by the Dutch radio station 3FM for the Dutch Red Cross.

If the schedule doesn’t change I will be speaking in the Africa Room on Friday between .

Update

I’ve uploaded my slides for this session (PowerPoint PPTX, 6,83MB).
You can also view my presentation on SlideShare (but the fonts get messed up):

Techdays 2013 NL – Serious Request met Windows Azure from Michaël Hompus

/

DotNed is the Dutch .NET usergroup and organizes several meetings each year for the .NET community. They also run a regular podcast covering several .NET development related topics like Visual Studio, Mono, ASP.NET MVC, Windows Phone and Windows Azure.

Triggered by my scheduled TechDays 2013 presentation, I was interviewed a few weeks ago by Maurice de Beijer about my experiences using Windows Azure to build a high available and scaling platform for the various applications used during “3FM Serious Request“.

You can listen to this 64 minute during podcast on the dotNed website. I’m sorry for the international crowd, it was recorded in Dutch.

/

When writing .NET code to access a SQL database we often rely on the Entity Framework (EF). The EF makes it very easy to retrieve data from the database by generating a SQL Query for us. But we shouldn’t trust it blindly as the EF can also generate a bad query. It will return the correct data yes, but at what performance cost?

I have a table with lots of data, and to keep the table as small as possible on disk and in memory I want to optimize the columns. This can be done by using varchar instead of nvarchar, date instead of datetime and also using tinyint instead of int. Of course you only can do this if your data allows this.

The problem

Changing a column in my table from int to tinyint gave me a storage and memory space win, but it also gave me a performance loss!

In my case the SQL column “HasSong” is a tinyint. EF translates this to a Byte Structure in the .NET model.

The following code:

var query = from d in dataEntities.Donations
            where d.HasSong == 1
            select d.DonationId;

produces this SQL Query:

SELECT
    [Extent1].[DonationId] AS [DonationId]
FROM
    [dbo].[Donations] AS [Extent1]
WHERE
    1 = CAST([Extent1].[HasSong] AS int)

When SQL encounters this CAST it will skip all Indexes that are on the HasSong column resulting in the query engine using non-optimized indexes or even worse: full table scans.

So this explains my performance loss, but how do we convince EF not to cast my byte to an int?

The familiar “Contains”

Browsing the internet gave me my first idea: using the familiar contains method I encountered on an earlier post about the EF: Joining an IQueryable with an IEnumerable.
I just have to add an Array with a single value.

So trying this:

var tinyintComparison = new byte[] { 1 };

var query = from d in dataEntities.Donations
            where tinyintComparison.Contains(d.HasSong)
            selectd.DonationId;

was not such a good idea as it throws an ArgumentException:
Screenshot showing Visual Studio debugger with the message "ArgumentException: DbExpressionBinding requires an input expression with a collection ResultType"
It did work for other people using a SMALLINT, so I guess an array of bytes is a special case reserved for working with binary data in your database.

The solution

Lucky enough we are not far from a solution, changing the array to a List<T> Class:

var tinyintComparison = new List<byte> { 1 };

var query = from d in dataEntities.Donations
            where tinyintComparison.Contains(d.HasSong)
            selectd.DonationId;

results in the following query:

SELECT
    [Extent1].[DonationId] AS [DonationId]
FROM
    [dbo].[Donations] AS [Extent1]
WHERE
    1 = [Extent1].[HasSong]

There we are! No more casting. The SQL query engine can use the correct indexes again and we still won disk and memory space.

Conclusion

If you don’t want a CAST in your SQL query when using a tinyint use the IList<T>.Contains Method.