imageThis post will show you how to use repositioning to create a responsive layout for your XAML Universal Windows app (UWP) using Grid and AdaptiveTrigger.


With Windows 10 and its UWP stack, making your app look nice on both mobile and desktop is one of the core requirements. The Responsive design 101 for Universal Windows Platform (UWP) apps guide on MSDN outlines six different ways for responsive design:

  • Reposition
  • Resize
  • Reflow
  • Reveal
  • Replace
  • Re-architect

In this post we’ll use the familiar Grid-control with the AdaptiveTrigger to reposition our app’s content. On desktops and tablets the app will use 2-column layout. On mobile devices (or when user resizes the app to have a small window) the second column drops under the first one.


AdaptiveTrigger is a new addition in Windows 10. You can use AdaptiveTrigger to automatically change the VisualState when the app’s width or height changes. For example the following Channel9-video contains good information about the AdaptiveTrigger.

The code

Here’s out app’s simple layout:

    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" x:Name="MainGrid">


        <Grid x:Name="FirstGrid" Grid.Column="0" Grid.Row="0" Background="#0078d7" />
        <Grid x:Name="SecondGrid" Grid.Column="1" Grid.Row="0" Background="#107C10" />


Without any VisualStates or AdaptiveTriggers, the app will look the same on all screen sizes:


But what we want is to reposition our SecondGrid under the FirstGridon mobile devices. To do this, we need to change the Grid.Column and Grid.Row of the SecondGrid:

                        <Setter Target="SecondGrid.(Grid.Column)" Value="0"/>
                        <Setter Target="SecondGrid.(Grid.Row)" Value="1"/>

Also, there’s no need for two columns so we modify the MainGrid for our needs:

                        <Setter Target="MainGrid.RowDefinitions[1].Height" Value="*"/>
                        <Setter Target="MainGrid.ColumnDefinitions[1].Width" Value="auto"/>

Last thing we do is change the margins to make things little prettier:

                        <Setter Target="MainGrid.Margin" Value="12"/>
                        <Setter Target="FirstGrid.Margin" Value="0 0 0 6"/>
                        <Setter Target="SecondGrid.Margin" Value="0 6 0 0"/>

And that’s it. Here’s all the VisualState changes combined. First the WideState (2-column layout):

                        <Setter Target="MainGrid.Margin" Value="24"/>
                        <Setter Target="MainGrid.RowDefinitions[1].Height" Value="auto"/>
                        <Setter Target="MainGrid.ColumnDefinitions[1].Width" Value="*"/>
                        <Setter Target="FirstGrid.Margin" Value="0 0 6 0"/>
                        <Setter Target="SecondGrid.Margin" Value="6 0 0 0"/>
                        <Setter Target="SecondGrid.(Grid.Column)" Value="1"/>
                        <Setter Target="SecondGrid.(Grid.Row)" Value="0"/>

And then the NarrowState (mobile layout):

                        <Setter Target="MainGrid.Margin" Value="12"/>
                        <Setter Target="FirstGrid.Margin" Value="0 0 0 6"/>
                        <Setter Target="SecondGrid.Margin" Value="0 6 0 0"/>
                        <Setter Target="MainGrid.RowDefinitions[1].Height" Value="*"/>
                        <Setter Target="MainGrid.ColumnDefinitions[1].Width" Value="auto"/>
                        <Setter Target="SecondGrid.(Grid.Column)" Value="0"/>
                        <Setter Target="SecondGrid.(Grid.Row)" Value="1"/>

With these few lines of XAML we have used repositioning to achieve a nice responsive layout.


Download source code

The full source code is available from GitHub.



Few years back I released and wrote about the NSQLFormatter. NSQLFormatter is an open-source SQL Beautifier / Formatter library written with C#.

The library is now available as a portable class library.You can get either the source code through GitHub or the PCL-compatible DLL through NuGet.

Source code: https://github.com/mikoskinen/NSQLFormatter-dotnet

Nuget: https://www.nuget.org/packages/NSQLFormatter/


Creating strings inside loops in VB.NET can cause subtle and easy-to-miss bugs. Here’s a simple example:

    Sub Main()

        For i As Integer = 1 To 4 Step 1

            Dim text As String
            text = text & i.ToString




    End Sub

As we are creating the textvariable inside the for loop, one would presume that this would ouput:





Instead, when run, we get this:


Check the compiler warnings and you’ll see:

Variable 'text' is used before it has been assigned a value. A null reference exception could result at runtime.

The problem can be easily fixed by assigning an empty value to text when it is declared:


Still, this can cause interesting issues if you don’t play close attention to compiler warnings.


We’re working with a Windows 8.1 Store App where we need to know the physical screen size of the display. Here’s some simple code which seems to do the trick in most cases:

            var width = Window.Current.Bounds.Width * (int)DisplayProperties.ResolutionScale / 100;
            var height = Window.Current.Bounds.Height * (int)DisplayProperties.ResolutionScale / 100;

            var dpi = DisplayInformation.GetForCurrentView().RawDpiY;

            var screenDiagonal = Math.Sqrt(Math.Pow(width / dpi, 2) +
                        Math.Pow(height / dpi, 2));

            return screenDiagonal.ToString();

Please note that the DPI will return 0 if you have two displays in duplicate mode: http://msdn.microsoft.com/en-us/library/windows/apps/windows.graphics.display.displayinformation.rawdpix


Windows Phone caches web requests aggressively. We’ve all seen a case where the first request to the web server works as expected but then the following requests fail to return up-to-date data. Instead of just adding the timestamp to the request URL, you can fix this issue on the server side.


Here’s a simple app next to Fiddler which demonstrates the problem. The app issues a web request with every button click:

        private async void DoRequest_OnClick(object sender, RoutedEventArgs e)
            var client = new WebClient();
            await client.DownloadStringTaskAsync("http://adafy.com");

            requestCount += 1;

            this.RequestCount.Text = requestCount.ToString();

First, a screenshots where user has clicked the button the first time:


And here’s what happens when she clicks the button the second time:


As you can see from the Fiddler, no request is sent to the server: Windows Phone returns the web request’s response from the cache.

The most often seen solution to this is to add a timestamp to the URL, this way bypassing the Windows Phone’s caching mechanisms. Example:


The requested URL changes every time, this way bypassing Windows Phone’s caching.


All this is because of the web request’s response headers.Make the server return the following Cache-Control header and your app will work exactly as you want:

Cache-Control: public, max-age=15, must-revalidate

Where max-age defines how long (in seconds) your Windows Phone app will cache the request.

By changing the headers you can configure how the app behaves. For example:

  1. You can force your app to make a fresh request every time (set max-age to 0).
  2. You can set exact caching (in seconds) for the requests.

Setting the headers on ASP.NET MVC

ASP.NET MVC offers multiple ways of configuring cache-control header. For example you can set the header on every action:

Response.Headers.Set("Cache-Control", "public, max-age=15, must-revalidate");

Or you can create a filter which is automatically executed after each request. The following StackOverflow questions show multiple solutions:



Setting the headers on Azure Blob Storage

If you use Azure Blob Storage as your app’s backend, you can set caching for each blob using the blob.SetProperties-method:

            var blob = container.GetBlockBlobReference(file);

            blob.Properties.CacheControl = string.Format("public, max-age={0}, must-revalidate", (int)cacheAge.TotalSeconds);
            blob.Properties.ContentType = contentType;