Universal App with SQLite – Part 2

This post is from Nicolò Carandini‘s blog post Universal App with SQLite – Part 2

In this series of posts, I’ll describe how to build a SQLite Test app that will run on Windows Runtime 8.1 Devices (Windows 8.1 and Windows Phone 8.1).

On the first post, I briefly introduced the new “Universal App” Visual Studio project type, and explained how to add SQLite to the project.

On this second post, we will see how to use the Universal App project type to avoid unnecessary duplication of code by sharing the things that remain the same for both Windows Store app and Windows Phone Store app, and how to take advantage of SQLite to manage locally stored data.

On the first post we’ve created a Universal Windows App (this is the official term for Apps built using the shared project tooling that target both Windows and Windows Phone ), with all the right references to the SQLite library.

To help us hiding all the intricacies of calling the SQLite APIs, now we will add the sqlite-net library on both Windows and Windows Phone projects, using NuGet:

As a result, we will have two copies of the two files “SQLite.cs” and “SQLiteAsync.cs”, one in the Windows project and one in the Windows Phone project:

To avoid unnecessary duplication, let’s start using the shared project:

  1. Move one copy of “SQLite.cs” and “SQLiteAsync.cs” files to the Shared project
  2. Delete the other copy.

At the end, this will be the new outcome:

Using sqlite-net is very simple and there are many posts describing how to use it, like Using SQLite in your Windows 8 Metro style applications by Matteo Pagani.

Problem is that some of them are a bit dated and something on the sqlite-net library has changed from then, so it’s better to repeat here the basic operations available:

Create / Open a database

To open a database named “People.db” (will be created if nonexistent):

By default, the sqlite-net library will create the database file on:

To check for the existence of the database file:

Create a table

We start defining the class that represent the table row:

As you can see, it’s possible to decorate the class and the properties with attributes defined in the sqlite-net library, in almost the same way we are used to do with DataAnnotation and EF. Here is the full list:

Class attribute:

  • [Table(Name)]

Property attributes:

  • [AutoIncrement]
  • [PrimaryKey]
  • [Column(Name)]
  • [Indexed] | [Indexed(string name, int order)]
  • [Unique]
  • [Ignore]
  • [MaxLength(int length)]
  • [Collation(string name)]
  • [NotNull]

Because the User class is part of our model that will be used by both the Windows and Windows Store app, the right place to create it is on a Model folder located into the shared project:

Now that we have defined the class that correspond to the table row, we can create the table, using the database connection:


The method will check for the existence of the table in the SQLite file and if not found it will create it. Moreover, if the class that represent the table row has changed, the method will try to update the SQLite table (actually, only the adding of new columns is supported).

It worth noting that the method will not destroy an existent table, so it can be redone without previously checking for the existence of the table.

Add a record to a table

This is super easy:

Add records to a table

Any IEnumerable collection can be added to the table (the IEnumerable item type must obviously be the same of the table creation one):

Retrieve records

We can query directly a table object using Linq:

or using the connection query method:

The SQL command can contain parameters:

Update records

Once retrieved, the object representing the table row can be easily modified at model level and persisted at database level:

Delete records

To delete a table row:

Drop a table

Deleting a table is also super easy:

You can download the demo solution on my OneDrive: http://1drv.ms/1kQ9sP0

This conclude my second post on how to use the Universal App project type to avoid unnecessary duplication of code by sharing the things that remain the same for both Windows Store app and Windows Phone Store app, and how to take advantage of SQLite to manage locally stored data.

Universal App with SQLite – Part 1

This post is from ‘s blog post Universal App with SQLite – Part 1

In this series of posts, I’ll describe how to build a SQLite Test app that will run on Windows Runtime 8.1 Devices (Windows 8.1 and Windows Phone 8.1).

On this first post, I will briefly introduce the new “Universal Apps” Visual Studio project type, and explain how to add SQLite to the project.

Windows Phone 8.1 is finally out (as a Developer Preview) and the convergence of platforms brought us a new type of Visual Studio project type: the “Universal Apps”:

The idea is simple, yet elegant and powerful. Now that Windows Phone has joined the party, we can have a single project folder that contains three projects, one for the Windows App, one for the Windows Phone Store App and one for all the things that we want to be shared by both the previous projects:

This way we can keep the things we need to do differently for Windows Store app and Windows Phone Store app (typically the UI) and put all the rest in the shared part without any unneeded duplication.

Ok, enough talking, so let’s move on and start creating the app.

First, you need to have Visual Studio 2013 and install the Visual Studio 2013 Update 2 Release Candidate.

Then you can create a new blank Universal App and call it “SQLiteTest”:

Now that you have your wonderful three-part project, you need to add SQLite. Actually, the only way to do so is via SDK extensions of Visual Studio and you need to add two of them, one for Windows Store app and one for Windows Phone Store app.

The first extension is available as a VSIX package built by the official SQLite Development Team from the Visual Studio Extensions Gallery:

It’s worth noting that the current version (3.8.4.3) has a flaw in the package metadata that prevent it to show up in the Visual Studio 2013 “Tools | Extensions and Updates” page. You need to go to the web page, download and install the VSIX package by yourself:

You can directly open it while downloading, authorize installation and click install when ready:

The second extension is also available as a VSIX package but is a preview version built by Tim Heuer of Microsoft as temporary workaround while the official package is still not available (I’ll update this post when it will be available).  now available from the SQLite team!

Same as before, you can directly open it while downloading, authorize installation and click install when ready:

To double check that everything is all right, you can open Visual Studio 2013 “Tools | Extensions and Updates” and look for installed SDKs:

Once you have downloaded and installed both VSIX packages, you are finally ready to add the SQLite references to your Universal App project.

First, right click to the References container of the SQLite.Test.Windows (Windows 8.1) project:

Then add the reference to the “SQLite for Windows Runtime (Windows 8.1)” library:

Second, right click to the References container of the “SQLite.Test.WindowsPhone (Windows Phone 8.1)” project:

Then add the reference to the “SQLite for Windows Runtime (Windows Phone 8.1)” library:

When done, you can see that the proper references to SQLite and Visual C++ 2013 Runtime have been added to respective projects:

Problem is, as you may have already noticed, that the references show a warning sign. If you try to build the solution, you will receive the same error for each of the four added references (below I’ve reported the one related to the SDK “SQLite.WinRT81, Version=3.8.4.3″):

“The processor architecture of the project being built “Any CPU” is not supported by the referenced SDK “SQLite.WinRT81, Version=3.8.4.3″. Please consider changing the targeted processor architecture of your project (in Visual Studio this can be done through the Configuration Manager) to one of the architectures supported by the SDK: “x86, x64, ARM”.

Don’t panic! As better explained in the Tim Heuer’s blog, these things are platform-specific and/or native and have dependencies on various native compiler/linker options or have been compiled in such a way that are different for the Phone device versus a tablet device.

The easy solution is to open the Configuration Manager and set the platform to x86 on both projects for Debug and Release configuration. Do not chose x64 or the XAML designer will not be able to show the UI.

This will not prevent you to create the different platform version to be deployed on the store, because when ready you will use the “Create App Packages…” command:

For the Windows Store app:

and the Windows Phone Store app:

Then will be the Store that automagically will deploy the right package for the device platform of the user that is downloading our beloved app from the store.

This conclude my first post on how to create (and successfully build) a Universal App project with SQLite.

On next post, we will see how to use the Universal App project type to avoid unnecessary duplication of code by sharing the things that remain the same for both Windows Store app and Windows Phone Store app, and how to take advantage of SQLite to manage locally stored data.

Introducing ASP.NET vNext

ASP.NET vNext is:

  • Cloud and server-optimized
  • ASP.NET MVC and Web API have been unified into a single programming model
  • No-compile developer experience
  • Dependency injection out of the box
  • Side by side – deploy the runtime and framework with your application
  • NuGet everything – even the runtime itself
  • All Open Source via the .NET Foundation and takes contributions

Read More… on Scott Hanselman‘s Blog

WordPress for Phone updated

WordPress for Phone has just been updated.

Get the update for all 191 countries from the Windows Phone store

Download Now! http://goo.gl/j6Fzhf

A first look at Windows Phone 8.1 Emulators

With Build 2014 started, we have a new Visual Studio 2013 Update 2 RC available. The update brings with it the new Windows Phone 8.1 Emulators.

Here are some screens from the emulator and my app Maps+ running on the emulator.

The emulator has new features like:

  • Volume up/down
  • Lock screen button
  • Camera button
  • Ability to sign in with Microsoft account to use Cortana

More about the emulator in later posts…

MSDN: Build apps that target Windows and Windows Phone 8.1 by using Visual Studio

This is a post from MSDN for the new Universal apps for Windows 8.1 and Windows Phone 8.1. Get the latest resources from http://dev.windows.com

You can build an app for Windows and Windows Phone 8.1 at the same time, and share code, user controls, styles, strings and other assets between them. This reduces the expense associated with building and maintaining an app for each type of device.

If you already have a Windows Store app, you can easily add support for a Windows Phone Store app. Similarly, if you start by creating a Windows Phone app, you can easily add support for a Windows Store app.

 

Develop an app that targets Windows and Windows Phone 8.1

To get started, pick a Universal project template in the New Project dialog box.

This image shows the universal project templates that are currently available for C#. Visual C++ has a similar set of Universal App templates..

Universal Project templates in Visual Studio

When you select a template and create a solution, three projects appear in Solution Explorer: a Windows Phone project, a project, and a Shared project.

This image shows a solution that appears when you choose a Blank App project template.

Converged project in Solution Explorer

  • The Windows Store project contains XAML pages and code that target Windows.
  • The Windows Phone project contains XAML pages and code that target Windows Phone 8.1.
  • The Shared project is a container for code that runs on both platforms. The contents of the Shared project are automatically included in both the Windows Phone and the Windows Store projects. There is no build output from the Shared project itself.

When you build the solution, Microsoft Visual Studio builds a Windows Phone Store app and a Windows Store app. When you run the solution, for example by pressing F5, the project that is set as the startup project is the one that runs. To set either the phone or Windows project as startup project, right click on the project node in Solution Explorer and choose Set as Startup Project. The project that you choose shows in bold in Solution Explorer. In the previous image, App1.Windows (Windows 8.1) is the startup project.

When the Windows project is the startup project, the Debug target dropdown displays options for the Windows Simulator or Local Machine. When the Phone project is the startup project, the dropdown displays options for Device as well as various phone emulators. In a C++ phone project, you must manually set the build configuration to the ARM platform in order to see the Device option and deploy the app to a physical device. The Win32 configuration is used for the phone emulators only. Set the platform by navigating to Project | Properties | Configuration Manager | Platform.

Get started writing a converged app

Consider starting with the template named Hub App (Universal Apps) instead of a Blank App. The Hub App template creates an app that has three pages. (Hub is the equivalent of Panorama in previous versions of Windows Phone.) You can find the Hub App template under the Universal Apps category. To read more about the Hub App project template, see Visual Studio templates.

This image shows the Hub App project template selected in the New Project dialog box.

Hub App template in Visual Studio

Write cross-platform code in the Shared project

In the Shared project, you typically write code that runs on both platforms. You can also use the #ifdef directive to isolate sections of code that are platform-specific. The constants WINDOWS_APP and WINDOWS_PHONE_APP are conveniently predefined for you. (In C++ use this directive: #if WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP)...#endif.

You can use drag-and-drop to move files from one of the platform-specific projects to the Shared project or vice versa to change the scope of the code.

Note

Platform context in the code editor

When you’re writing code in the Shared project, the Visual Studio code editor uses a context that targets one platform or the other. In C#, the Intellisense that you see as you write code is specific to the context of the code editor – that is, specific to Windows or to Windows Phone 8.1. In C++, the context (and not the startup project) determines whether the code inside the #if WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP directive is greyed out or not.

If you use an API in shared code that’s not supported on both platforms, an error message will identify this API when you build the project. You can confirm that you’re using cross-platform APIs, however, without building the project. Switch the editor context in the drop-down list to the other platform to see squiggly lines under APIs that are not supported on that platform. Then isolate those APIs by using the #ifdef directive.

This image shows the context chooser drop-down list in the Visual Studio code editor.

Context switcher drop-down list in the code editor

Add support for a Windows or Windows Phone 8.1

If you’ve published a Windows Store app already, it’s very easy to reuse some of the code and publish a version of your app for Windows Phone 8.1. Similarly, if you started by creating a Windows Phone 8.1 app, you can modify your solution to build for Windows desktops and tablets as well. To add support for one type of device or another, open the shortcut menu for the project and choose either the Add Windows Phone 8.1 or Add Windows 8.1

Adding a Windows Phone 8.1 project

Depending on which type of app your adding support for, Visual Studio adds Windows Phone 8.1 or Windows Store project to your solution. Visual Studio also adds a Shared project as well. This image shows a project after a Windows Phone project has been added.

Phone project added to solution.

Move files into the Shared project

You can move any code that you want to share between apps to the Shared project. For example, if you created your app by using a Visual Studio template, consider moving the Common, DataModel and Strings folder into the Shared project. You can even move App.xaml into the Shared project. More on that later in this topic. This image shows a solution after files and folders have been moved into the Shared project.

Files moved into the shared project

You’ll probably receive some compiler errors in the code that you’ve shared. In many cases, you can resolve the errors adding assembly references to the new app project. (In C++, if both projects depend on a LIB or DLL, you have to specify it separately in each project.) For example, if code refers to the JsonConvert type in the Newtonsoft.json assembly, that code might have compiled before you moved it into the Shared folder because your Windows Store app contained a reference to the that assembly. Now that you’ve moved that code into the Shared project, you’ll have to also add the Newtonsoft.json assembly to the Windows Phone project. This image shows assemblies added to both projects.

Assembly references added to both projects

If your shared code uses API’s that are specific to Windows, use the #ifdef directive to isolate that section of code. You can isolate sections of Windows-specific code by using the WINDOWS_APP constant. Apply the WINDOWS_PHONE_APP constant to isolate sections of code specific to Windows Phone 8.1. The next section shows an example of how to apply these constants, and the analgous constants used in C++

Note  Moving files from one project to another does not physically move them in the file system. In a C++ project, this means that if you drag files to another project, you might have to adjust header file paths in your #include directives.

Share the App.xaml

In a brand new Universal app, Visual Studio places App.xaml into the Shared project. You can do this with your converted solution, but you’ll have to set the Build Action property of the page to ApplicationDefinition.

  1. In Solution Explorer, in the Shared project, select the App.xaml file.
  2. Select View > Properties Window.
  3. In the Properties window, in Build Action drop-down list, select ApplicationDefinition.

You’ll also have to decide how you want to handle code that opens the first page of your app. For example, the App.xaml page of a solution might start a page named HubPage as shown below:

if (!rootFrame.Navigate(typeof(HubPage)))
{
    throw new Exception(“Failed to create initial page”);
}

For this code to compile, both projects must contain a page named HubPage. If you would rather use a page by a different name, you’ll have to add #ifdef directives as shown below:

#if WINDOWS_APP
                if (!rootFrame.Navigate(typeof(HubPage)))
#endif
#if WINDOWS_PHONE_APP
                if (!rootFrame.Navigate(typeof(WindowsPhoneStartPage)))
#endif
                {
                    throw new Exception("Failed to create initial page");
                }


Finally, ensure that any styles defined in your App.xaml file use resources that are available in both types of apps. Otherwise, move those style definitions into the Windows Store or Windows Phone project

Source: MSDN

Review Nokia Refocus app

The app is simple and straight forward. The app will take multiple pictures with different focus levels to show you a perfect all focused picture.

from the app bar you can then choose to focus a particular object or the entire scene.

the app also has a color pop feature, which will allow you to select a particular color in the picture while the rest of the picture is in black and white.

Here is a picture taken from this app on Lumia 820.

 

I will show a step by step guide for this app in the next post. Meanwhile check out “Nokia Refocus” for Windows Phone http://www.windowsphone.com/s?appid=0b5cc26d-a723-4c69-8be3-66bbd9b2bed1

via WordPress for Phone http://goo.gl/j6Fzhf

 

Supporting large screen Windows Phone devices

With the latest GDR 3 Update, Windows Phone 8 now support new 6″ devices like the Nokia Lumia 1520 and Nokia Lumia 1320. As always your existing apps will continue to work on these new devices without any change in the code. However, you can take additional steps to use this new screen real estate more efficiently.

There are a couple of posts on the web which tell how to modify your app for the new screen size. Have a look at them if that’s your thing.

I would like to show you a simper way of using all the above resource in you app.

1. Device Properties

Get the device properties using the DeviceExtendedProperties class.

object temp;

// Get PhysicalScreenResolution
if (!DeviceExtendedProperties.TryGetValue("PhysicalScreenResolution", out temp))
    return false;
screenResolution = (Size)temp;

if (!DeviceExtendedProperties.TryGetValue("RawDpiX", out temp) || (double)temp == 0d)
    return false;

dpi = (double)temp;

2. Compute scale factor

We now then use the above properties to determine the actual scaling factor. The simplified logic for scaling factor is
factor  = actual screen resolution / reported app width / aspect ratio.

However, in reality we need to apply certain calculation depending on physical device size and screen resolution. This is because not all 720p and 1080p devices have the same scaling ratio and dpi.

Here is the code adapted from the DisplayInformationEx class on msdn:

var width = App.Current.Host.Content.ActualWidth;
var physicalSize = new Size(screenResolution.Width / dpi, screenResolution.Height / dpi);
var scale = Math.Max(1, physicalSize.Width / DisplayConstants.BaselineWidthInInches);
var idealViewWidth = Math.Min(DisplayConstants.BaselineWidthInViewPixels * scale, screenResolution.Width);
var idealScale = screenResolution.Width / idealViewWidth;
RawPixelsPerViewPixel = idealScale.NudgeToClosestPoint(1); //bucketizedScale
var ViewResolution = new Size(screenResolution.Width / RawPixelsPerViewPixel, screenResolution.Height / RawPixelsPerViewPixel);

Scale = Math.Max(1, Math.Min(ViewResolution.Width / Application.Current.Host.Content.ActualWidth, ViewResolution.Height / Application.Current.Host.Content.ActualHeight));

If this logic is too complicated, well it is. Thanks to Microsoft for doing a wonderful job!

3. ZoomBox control

The next part in our change is to wrap any control we want to scale in a zoom box. This control is also adapted from the msdn sample without the frills

    [TemplatePart(Name = ZoomBox.ContentHolderPartName, Type = typeof(UIElement))]
    public class ZoomBox : ContentControl
    {
        public const string ContentHolderPartName = "contentHolder";

        readonly ScaleTransform transform = new ScaleTransform();
        UIElement contentHolder;

        public static readonly DependencyProperty ZoomFactorProperty = DependencyProperty.Register("ZoomFactor", typeof(double), typeof(ZoomBox), new PropertyMetadata(1.0, OnZoomFactorPropertyChanged));
        public double ZoomFactor
        {
            get { return (double)GetValue(ZoomFactorProperty); }
            set { SetValue(ZoomFactorProperty, value); }
        }

        static void OnZoomFactorPropertyChanged(DependencyObject source, DependencyPropertyChangedEventArgs e)
        {
            var control = (ZoomBox)source;
            if (double.IsNaN((double)e.NewValue) || (double)e.NewValue <= 0)
            {
                control.ZoomFactor = (double)e.OldValue;
                throw new ArgumentOutOfRangeException("ZoomFactor", "must be a positive number");
            }
            control.InvalidateMeasure();
        }

        public static ZoomBox GetForElement(UIElement element)
        {
            var currentElement = element;
            while (currentElement != null)
            {
                if (currentElement is ZoomBox)
                    return currentElement as ZoomBox;

                currentElement = VisualTreeHelper.GetParent(currentElement) as UIElement;
            }

            return null;
        }

        public ZoomBox()
        {
            transform = new ScaleTransform { ScaleX = 1, ScaleY = 1 };
            DefaultStyleKey = typeof(ZoomBox);
        }

        public override void OnApplyTemplate()
        {
            if (contentHolder != null)
                contentHolder.RenderTransform = null;
            contentHolder = null;

            base.OnApplyTemplate();

            var temp = GetTemplateChild(ContentHolderPartName) as UIElement;
            if (temp == null)
                return;

            contentHolder = temp;
            if (ZoomFactor != 1)
                contentHolder.RenderTransform = transform;
        }

        protected override Size ArrangeOverride(Size finalSizeInHostCoordinates)
        {
            var effectiveZoomFactor = ZoomFactor;
            var finalSizeInViewCoordinates = finalSizeInHostCoordinates.Scale(effectiveZoomFactor);
            var requiredSizeInViewCoordinates = base.ArrangeOverride(finalSizeInViewCoordinates);
            var requiredSizeInHostCoordinates = requiredSizeInViewCoordinates.Scale(1 / effectiveZoomFactor);

            if (effectiveZoomFactor != 1)
            {
                transform.ScaleX = transform.ScaleY = 1 / effectiveZoomFactor;
                contentHolder.RenderTransform = transform;
            }
            else
                contentHolder.RenderTransform = null;

            return requiredSizeInHostCoordinates;
        }

        protected override Size MeasureOverride(Size availableSizeInHostCoordinates)
        {
            var effectiveZoomFactor = ZoomFactor;
            var availableSizeInViewCoordinates = availableSizeInHostCoordinates.Scale(effectiveZoomFactor);
            var desiredSizeInViewCoordinates = base.MeasureOverride(availableSizeInViewCoordinates);
            var desiredSizeInHostCoordinates = desiredSizeInViewCoordinates.Scale(1 / effectiveZoomFactor);

            return desiredSizeInHostCoordinates;
        }
    }

You supply the scaling factor computed earlier to this control.

4. Usage

You use these controls as below:

<!-- App Resources section -->
<local:SizeHelper x:Key="SizeHelper" />

<!-- Page Content section -->
<controls:ScaledView
                   ZoomFactor="{Binding Scale,Source={StaticResource SizeHelper}}" >
    <Grid><!--You controls go here--></Grid>
</controls:ScaledView>

The ScaledView control is a wrapper to provide the scaling factor to the entire app without the need to compute it again. You can find the entire source code including the ScaledView control at the end of this post.

Sample

The general usage of this would be on lists and grids to use the extra space. I have implemented this in my app Maps+. here are the screenshots using WXGA and 1080p devices. Do download and rate my app.

If you observe closely, originally the 1080p screens appear enlarged with a little more space towards the bottom. After scaling the sizes are comparable with the WXGA screens and provide more space of results.

Download Maps+

(Note: I have just published the app update and will take some time to appear in the store. The original app is available.)

Conclusion

Updating your apps for ne large screen devices is almost simple. (it could have been simpler if MS wanted it to be). Adding these few little things will help provide a better user experience to users. If you have any questions, let me know.

Entire source code is below:

using Microsoft.Phone.Info;
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
namespace ScalingUI.Controls
{

/*
Put this in the App.xaml Resources section:
<local:SizeHelper x:Key="SizeHelper" />

Put this inside your page:
<controls:ScaledView
                   ZoomFactor="{Binding Scale,Source={StaticResource SizeHelper}}" >
    <Grid><!--You controls go here--></Grid>
</controls:ScaledView>

*/
    public static class DisplayConstants
    {
        public const double AspectRatio16To9 = 16.0 / 9.0;
        public const double AspectRatio15To9 = 15.0 / 9.0;

        public static readonly double DiagonalToWidthRatio16To9 = 9.0 / Math.Sqrt(Math.Pow(16, 2) + Math.Pow(9, 2));
        public static readonly double DiagonalToWidthRatio15To9 = 9.0 / Math.Sqrt(Math.Pow(15, 2) + Math.Pow(9, 2));

        public const double BaselineDiagonalInInches15To9HighRes = 4.5; // Lumia 920
        public const double BaselineDiagonalInInches15To9LoRes = 4.0; // Lumia 520
        public const double BaselineDiagonalInInches16To9 = 4.3; // HTC 8X

        // We use 15:9 aspect ratio, 4.5" diagonal with 480px view resolution as the baseline for scaling / relayout
        //  * Any size less than 4.5" will get scaled down
        //  * Any size greater than 4.5" will get more layout space
        // Note that 16:9 displays are skinnier than 15:9, so the cutover isn't exactly 4.5" for them
        internal static readonly double BaselineWidthInInches = BaselineDiagonalInInches15To9HighRes * DiagonalToWidthRatio15To9;
        internal const int BaselineWidthInViewPixels = 480;
    }

    public class SizeHelper : DependencyObject
    {
        public SizeHelper()
        {
            try
            {
                //Not for WVGA and WXGA.
                if (App.Current.Host.Content.ScaleFactor != 150) return;
                Size screenResolution;
                double dpi;
                if (!GetDeviceProperties(out screenResolution, out dpi)) return;

                //Calculation taken from DisplayInformationEx
                //http://blogs.windows.com/windows_phone/b/wpdev/archive/2013/11/22/taking-advantage-of-large-screen-windows-phones.aspx
                var width = App.Current.Host.Content.ActualWidth;
                var physicalSize = new Size(screenResolution.Width / dpi, screenResolution.Height / dpi);
                var scale = Math.Max(1, physicalSize.Width / DisplayConstants.BaselineWidthInInches);
                var idealViewWidth = Math.Min(DisplayConstants.BaselineWidthInViewPixels * scale, screenResolution.Width);
                var idealScale = screenResolution.Width / idealViewWidth;
                RawPixelsPerViewPixel = idealScale.NudgeToClosestPoint(1); //bucketizedScale
                var ViewResolution = new Size(screenResolution.Width / RawPixelsPerViewPixel, screenResolution.Height / RawPixelsPerViewPixel);

                Scale = Math.Max(1, Math.Min(ViewResolution.Width / Application.Current.Host.Content.ActualWidth, ViewResolution.Height / Application.Current.Host.Content.ActualHeight));

            }
            catch { }
        }

        private static bool GetDeviceProperties(out Size screenResolution, out double dpi)
        {
            screenResolution = new Size();
            dpi = 0;

            object temp;

            // Get PhysicalScreenResolution
            if (!DeviceExtendedProperties.TryGetValue("PhysicalScreenResolution", out temp))
                return false;
            screenResolution = (Size)temp;

            // Get RawDpi
#if DEBUG

            // Raw Dpi is not be available on the emulator.
            /*
             * Known RAW DPI for some devices
             * "HTC 8S or Lumia 520"        233.24  WVGA
             * "Lumia 822"                  222.13  WVGA
             * "HTC 8X"                     341.54  720P
             * "Lumia 920"                  331.72  WXGA
             * "Samsung ATIV S"             305.96  720P
             * "Generic 5\" 720p"           293.72  720P
             * "Generic 5.5\" Full HD",     400.53  1080P
             * "Lumia 1320",                244.77  720P
             * "Lumia 1520",                367.15  1080P
             * "Generic 6.5\" Full HD",     338.91  1080P
             */
            var w = screenResolution.Width;
            switch ((int)w)
            {
                // You can change thses values as per your test devices
                case 720: temp = 244D; break;
                case 1080: temp = 368D; break;
                default:
                    break;
            }
#else
            if (!DeviceExtendedProperties.TryGetValue("RawDpiX", out temp) || (double)temp == 0d)
                return false;

#endif
            dpi = (double)temp;

            return true;
        }

        public double Scale
        {
            get { return (double)GetValue(ScaleProperty); }
            set { SetValue(ScaleProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Scale.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty ScaleProperty =
            DependencyProperty.Register("Scale", typeof(double), typeof(SizeHelper), new PropertyMetadata(1D));

        public double RawPixelsPerViewPixel { get; set; }
    }

    // Source://http://blogs.windows.com/windows_phone/b/wpdev/archive/2013/11/22/taking-advantage-of-large-screen-windows-phones.aspx
    [TemplatePart(Name = ZoomBox.ContentHolderPartName, Type = typeof(UIElement))]
    public class ZoomBox : ContentControl
    {
        public const string ContentHolderPartName = "contentHolder";

        readonly ScaleTransform transform = new ScaleTransform();
        UIElement contentHolder;

        public static readonly DependencyProperty ZoomFactorProperty = DependencyProperty.Register("ZoomFactor", typeof(double), typeof(ZoomBox), new PropertyMetadata(1.0, OnZoomFactorPropertyChanged));
        public double ZoomFactor
        {
            get { return (double)GetValue(ZoomFactorProperty); }
            set { SetValue(ZoomFactorProperty, value); }
        }

        static void OnZoomFactorPropertyChanged(DependencyObject source, DependencyPropertyChangedEventArgs e)
        {
            var control = (ZoomBox)source;
            if (double.IsNaN((double)e.NewValue) || (double)e.NewValue <= 0)
            {
                control.ZoomFactor = (double)e.OldValue;
                throw new ArgumentOutOfRangeException("ZoomFactor", "must be a positive number");
            }
            control.InvalidateMeasure();
        }

        public static ZoomBox GetForElement(UIElement element)
        {
            var currentElement = element;
            while (currentElement != null)
            {
                if (currentElement is ZoomBox)
                    return currentElement as ZoomBox;

                currentElement = VisualTreeHelper.GetParent(currentElement) as UIElement;
            }

            return null;
        }

        public ZoomBox()
        {
            transform = new ScaleTransform { ScaleX = 1, ScaleY = 1 };
            DefaultStyleKey = typeof(ZoomBox);
        }

        public override void OnApplyTemplate()
        {
            if (contentHolder != null)
                contentHolder.RenderTransform = null;
            contentHolder = null;

            base.OnApplyTemplate();

            var temp = GetTemplateChild(ContentHolderPartName) as UIElement;
            if (temp == null)
                return;

            contentHolder = temp;
            if (ZoomFactor != 1)
                contentHolder.RenderTransform = transform;
        }

        protected override Size ArrangeOverride(Size finalSizeInHostCoordinates)
        {
            var effectiveZoomFactor = ZoomFactor;
            var finalSizeInViewCoordinates = finalSizeInHostCoordinates.Scale(effectiveZoomFactor);
            var requiredSizeInViewCoordinates = base.ArrangeOverride(finalSizeInViewCoordinates);
            var requiredSizeInHostCoordinates = requiredSizeInViewCoordinates.Scale(1 / effectiveZoomFactor);

            if (effectiveZoomFactor != 1)
            {
                transform.ScaleX = transform.ScaleY = 1 / effectiveZoomFactor;
                contentHolder.RenderTransform = transform;
            }
            else
                contentHolder.RenderTransform = null;

#if LOG_MEASURE_ARRANGE_OVERRIDE
      Debug.WriteLine("*** ArrangeOverride ***");
      Debug.WriteLine("  input size (host coordinates):    {0:#.} x {1:#.}", finalSizeInHostCoordinates.Width, finalSizeInHostCoordinates.Height);
      Debug.WriteLine("  converted (view coordinates):     {0:#.} x {1:#.}", finalSizeInViewCoordinates.Width, finalSizeInViewCoordinates.Height);
      Debug.WriteLine("  required size (view coordinates): {0:#} x {1:#.}", requiredSizeInViewCoordinates.Width, requiredSizeInViewCoordinates.Height);
      Debug.WriteLine("  scaling factor:                   {0:#.##}", ZoomFactor);
      Debug.WriteLine("  returning (host coordinates):     {0:#.} x {1:#.}", requiredSizeInHostCoordinates.Width, requiredSizeInHostCoordinates.Height);
#endif

            return requiredSizeInHostCoordinates;
        }

        protected override Size MeasureOverride(Size availableSizeInHostCoordinates)
        {
            var effectiveZoomFactor = ZoomFactor;
            var availableSizeInViewCoordinates = availableSizeInHostCoordinates.Scale(effectiveZoomFactor);
            var desiredSizeInViewCoordinates = base.MeasureOverride(availableSizeInViewCoordinates);
            var desiredSizeInHostCoordinates = desiredSizeInViewCoordinates.Scale(1 / effectiveZoomFactor);

#if LOG_MEASURE_ARRANGE_OVERRIDE
      Debug.WriteLine("*** MeasureOverride ***");
      Debug.WriteLine("  input size (host coordinates):    {0:#.} x {1:#.}", availableSizeInHostCoordinates.Width, availableSizeInHostCoordinates.Height);
      Debug.WriteLine("  converted (view coordinates):     {0:#.} x {1:#.}", availableSizeInViewCoordinates.Width, availableSizeInViewCoordinates.Height);
      Debug.WriteLine("  required size (view coordinates): {0:#} x {1:#.}", desiredSizeInViewCoordinates.Width, desiredSizeInViewCoordinates.Height);
      Debug.WriteLine("  scaling factor:                   {0:#.##}", ZoomFactor);
      Debug.WriteLine("  returning (host coordinates):     {0:#.} x {1:#.}", desiredSizeInHostCoordinates.Width, desiredSizeInHostCoordinates.Height);
#endif

            return desiredSizeInHostCoordinates;
        }
    }

    static class Ex
    {
        public const double Epsilon = 0.001;
        public static double NudgeToClosestPoint(this double currentValue, int nudgeValue)
        {
            var newValue = currentValue * 10 / nudgeValue;
            newValue = Math.Floor(newValue + Epsilon);
            return newValue / 10 * nudgeValue;
        }

        public static Size Scale(this Size size, double scaleFactor)
        {
            Size scaledSize = new Size();
            var h = size.Height;
            scaledSize.Height = Double.IsInfinity(h) ? h : h * scaleFactor;
            var w = size.Width;
            scaledSize.Width = Double.IsInfinity(w) ? w : w * scaleFactor;
            return scaledSize;
        }
    }

}

Launching Skype from your own Windows Store App

You can launch Skype using the uri pattern in Windows 8.

Skype supports the following protocols

  • skype
  • tel
  • sms
  • message-skype-com
  • message-messenger
  • audiocall-messenger
  • videocall-messenger
  • audiocall-skype-com
  • videocall-skype-com
var chatTo = new Uri("message-skype-com:" + UserNameTextBox.Text);
await Windows.System.Launcher.LaunchUriAsync(chatTo);

More details and samples on Geert van der Cruijsen’s blog

ASP.NET App Suspend – responsive shared .NET web hosting

From ASP.NET App Suspend – responsive shared .NET web hosting http://t.co/N7xbjwR0Ho

Suspend is the new terminate

ASP.NET App Suspend is a new feature in the .NET Framework 4.5.1 that makes ASP.NET sites much more responsive and enables you to host more sites on a single server. It is very well suited for commercial web hosters, like Windows Azure Web Sites, and Enterprise IT web hosting.

ASP.NET App Suspend is a self-tuning mechanism for web hosting, a little bit like CLR GC generations (if you squint). The addition of suspend establishes three states that a site can be in on a given machine. You can see the three states in the diagram, below.

clip_image004

All sites start out as inactive. As sites are requested, they are loaded into memory, become active, and respond to page requests. After sites have been idle, as determined by the timeout setting, they will be suspended. Suspended sites effectively lose access to the CPU, making CPU cycles and most of the memory they were using available for requests to other sites. However, they are kept in a state – this is the new suspended state – by which they can be resumed very quickly and respond to traffic again.

Usage scenarios

Scenarios that can benefit from ASP.NET App Suspend.

  • Shared hosting (commercial hosting or enterprise IT)        Companies selling or taking advantage of shared hosting can pack many more sites on a given machine, while providing much more responsive site experience.
  • Switch to shared hosting        Web site owners can take advantage of low-cost shared hosting while delivering the responsive experience that they want.
  • Hot spare for large sites        Large high-traffic sites can maintain spares in suspend, ready for when one of the servers behind a load balancer goes down (planned or unplanned).
  • Disaster recovery        Large high-traffic sites can maintain spares in suspend in a backup datacenter, ready for when the main data center goes down or otherwise becomes inaccessible.

Summary

ASP.NET App Suspend is a new feature for ASP.NET, available in the .NET Framework 4.5.1 on Windows Server 2012 R2. It delivers much better startup responsiveness for sites that do not get consistent traffic and would otherwise not be kept loaded in a responsive state at all times.

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: