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.

WordPress for Phone now in store

Shubhan Chemburkar:

Get my new updated app for a free trial

Originally posted on WordPress for Phone:

The new, refreshed WordPress for Phone now available in the Windows Phone store.

With this update we have added a lot of new features and an exciting new look and feel.

Features

• Get the latest “Freshly Pressed” posts.
• WordPress Reader – Get posts from blogs you follow.
• My Blogs – Sign-in to manage all your blogs from your phone.
• Blogs stats – Weekly and monthly views for your blogs.
• Easy to use Post editing and publishing.
• Comments – See latest comments for your blog.
• Explore – The latest from the world of WordPress. Find who is writing about what instantly on WordPress.

Get the free trial right now!!!

Download now

View original

LongListSelector control design guidelines for Windows Phone

The new LongListSelector control in Windows Phone 8 gives app users the ability to jump directly to a spot within a list instead of scrolling through the list to find the item they want. By using this control in your app, you can help users parse large amounts of data more efficiently, and you can more easily work longer lists of data into your app’s design.

LongListSelector

Appearance and action

Like the ListBox control, the LongListSelector control presents a fixed-sized scrolling selector of items in a list. A user can pan or flick vertically to scroll through items in the list. The user taps the control to select an item in the list.

However, when the user pans through a list, the panning stops at the point in the list where the user’s finger stops moving, or when the user lifts their finger from the phone screen. When the user flicks on the list, the list scrolls and then slows to a stop unless the user taps in the list, in which case, the scrolling—the effect of the flick gesture—stops. However, if scrolling slows to a specified speed, the tap gesture instead selects an item in the list instead of only stopping the scrolling action.

While the list is scrolling, the page can’t be pivoted left or right unless the scroll has slowed down to a certain speed.

When the end of the list is reached, it will then scroll up to display the empty section and “rubber band” back to rest in place. Flicking at the end of the list causes it to rubber band back; the list won’t wrap to the beginning. However, panning can wrap the list back to the beginning if you want to design this ability in your app.

Standard use

You use a LongListSelector control to conserve screen real estate when you want to present a long list of words, numbers, or visual elements from which the user is expected to choose. With the LongListSelector control, the user efficiently selects and then “jumps to” the list item they want.

Choosing the right control

Use a LongListSelector control when the user needs to choose from eight or more items in a list. If the list has four or fewer items, use grouped RadioButton controls instead of a LongListSelector control.

A LongListSelector control organizes a list of items vertically. If you want to present list items horizontally, particularly if the items are graphics or photos, consider instead using the ScrollViewer control.

The long list navigation experience

You have two options for setting up long-list navigation in your app:

  • Alphabetical list. Letters with no items listed are grayed out.
  • Group headers. When a user taps on a group header they activate the Quick Jump List. Your app must provide a list of group headers for this function to work. You’ll need to configure your app’s data source to be grouped in the categories you want for the Long List Navigation to display. If you use group headers in your app and a section is empty, that section will appear as grayed out.

LongListSelector_GroupHeader

Group Header Navigation: 1) User taps the group header on the list that has enabled Long List Navigation. 2) User is taken to Quick Jump List. 3) User jumps to the top of the group selected. 4) Long List Navigation based on Group Header will provide a header list.

Design guidelines

Using the  LongListSelector control is a clean and active way to present a long list of options, but note that a list can be too long. Consider using a table view for a list that contains more than a few dozen items.  Also remember to:

  • Use strong sans-serif typefaces; make list item text at least 12 pixels in height; and be sure that the text is legible from all angles and sizes.
  • Reserve illumination, effects, animations, or other ornamentation for scenarios that use touch feedback or selected states. Items in LongListSelector controls should have a strong visual reaction when users touch them.

Sample code


    <phone:PhoneApplicationPage.Resources>
        <DataTemplate x:Key="AddrBookItemTemplate">
            <StackPanel VerticalAlignment="Top">
                <TextBlock FontWeight="Bold"  Text="{Binding FirstName}" />
                <TextBlock Text="{Binding LastName}" />
                <TextBlock Text="{Binding Address}" />
                <TextBlock Text="{Binding Phone}" />
            </StackPanel>
        </DataTemplate>
        <DataTemplate x:Key="AddrBookGroupHeaderTemplate">
            <Border Background="Transparent" Padding="5">
                <Border Background="{StaticResource PhoneAccentBrush}" BorderBrush="{StaticResource PhoneAccentBrush}" BorderThickness="2" Width="62" Height="62" Margin="0,0,18,0" HorizontalAlignment="Left">
                    <TextBlock Text="{Binding Key}" Foreground="{StaticResource PhoneForegroundBrush}" FontSize="48" Padding="6" FontFamily="{StaticResource PhoneFontFamilySemiLight}" HorizontalAlignment="Left" VerticalAlignment="Center"/>
                </Border>
            </Border>
        </DataTemplate>
<phone:JumpListItemBackgroundConverter x:Key="BackgroundConverter"/>
<phone:JumpListItemForegroundConverter x:Key="ForegroundConverter"/>
<style x:Key="AddrBookJumpListStyle" TargetType="phone:LongListSelector>
 <Setter Property="GridCellSize" Value="113,113"/>
 <Setter Property="LayoutMode" Value="Grid" />
 <Setter Property="ItemTemplate">
 <Setter.Value>
 <DataTemplate>
 <Border Background="{Binding Converter={StaticResource BackgroundConverter}}" Width="113" Height="113" Margin="6" >
 <TextBlock Text="{Binding Key}" FontFamily="{StaticResource PhoneFontFamilySemiBold}" FontSize="48" Padding="6" Foreground="{Binding Converter={StaticResource ForegroundConverter}}" VerticalAlignment="Center"/>
 </Border>
 </DataTemplate>
 </Setter.Value>
 </Setter>
 </Style>
 </phone:PhoneApplicationPage.Resources>

 <phone:LongListSelector
 x:Name="AddrBook"
 JumpListStyle="{StaticResource AddrBookJumpListStyle}"
 Background="Transparent"
 GroupHeaderTemplate="{StaticResource AddrBookGroupHeaderTemplate}"
 ItemTemplate="{StaticResource AddrBookItemTemplate}"
 LayoutMode="List"
 IsGroupingEnabled="true"
HideEmptyGroups ="true"/>

Related Links

Windows 8.1 says, “Forget all that Design Stuff from Windows 8.0”

WHAT DESIGNERS HAD BETTER KNOW ABOUT WINDOWS 8.1

Let’s be perfectly clear, the Windows Design Guidelines in Windows 8.1 are, at a high-level, identical to those in Windows 8.0. However, in their practical and tactical guidance they are so different, that idyllic Windows 8.1 apps would potentially fail Windows 8.0 Store Certification. These guidelines, now hardwired into Microsoft developers and designers, remain consistent and contrarian to the Windows 8.0 guidance.

Microsoft Design Principles

The 5 core principles of the Windows Style, or the Microsoft Design Principles are unchanged. They are: 1) Pride in Craftsmanship, 2) Fast and Fluid, 3) Authentically Digital, 4) Do more with Less, and 5) Win as one. They have not changed in practice or in theory.

Navigation diagram for an example food app

More at Windows 8.1 says, “Forget all that Design Stuff from Windows 8.0”

CROSS APPLY Explained

CROSS APPLY could be used as a replacement for correlated sub queries and derived tables.  That’s what we’ll discuss today.

I never liked correlated subqueries because it always seemed like adding full blown queries in the select list was confusing and improper.

SELECT
SalesOrderID           = soh.SalesOrderID,
OrderDate              = soh.OrderDate,
MaxUnitPrice           = (SELECT MAX(sod.UnitPrice)
FROM Sales.SalesOrderDetail sod
WHERE soh.SalesOrderID = sod.SalesOrderID)
FROM AdventureWorks.Sales.SalesOrderHeader AS soh

It always seemed to me that these operations should go below the FROM clause.  So to get around this, I would typically create a derived table.  Which didn’t completely feel right either, but it was still just a bit cleaner:

SELECT
    soh.SalesOrderID,
    soh.OrderDate,
    sod.max_unit_price
FROM AdventureWorks.Sales.SalesOrderHeader AS soh
JOIN (
    SELECT
        max_unit_price = MAX(sod.UnitPrice),
        SalesOrderID
    FROM Sales.SalesOrderDetail AS sod
    GROUP BY sod.SalesOrderID ) sod
ON sod.SalesOrderID = soh.SalesOrderID

What made this ugly was the need to use the GROUP BY clause because we could not correlate.  Also, even though SQL almost always generates the same execution plan as a correlated sub query, there were times when the logic inside the derived table got so complex, that it would not limit the result set of the derived table by inferring the correlation first.  This made this kind of query sometimes impractical.

Luckily, this is where the CROSS APPLY steps in so nicely.  It gives us the best of both worlds by allowing us to correlate AND not have the query embedded in the select list:

SELECT
     soh.SalesOrderID,
     soh.OrderDate,
     sod.max_unit_price
FROM AdventureWorks.Sales.SalesOrderHeader AS soh
CROSS APPLY (
     SELECT
     max_unit_price = MAX(sod.UnitPrice)
     FROM Sales.SalesOrderDetail AS sod
     WHERE soh.SalesOrderID = sod.SalesOrderID ) sod

The other advantage this has over the correlated sub query is when we want to add more columns in our SELECT list, we do not have to completely repeat the entire query.  We still have it in one place, making it somewhat modular.  So instead of this:

SELECT
     SalesOrderID           = soh.SalesOrderID ,
     OrderDate              = soh.OrderDate ,
MaxUnitPrice           = (SELECT MAX(sod.UnitPrice)
                               FROM Sales.SalesOrderDetail sod
                               WHERE soh.SalesOrderID = sod.SalesOrderID) ,
SumLineTotal           = (SELECT SUM(LineTotal)
                               FROM Sales.SalesOrderDetail sod
WHERE soh.SalesOrderID = sod.SalesOrderID)
FROM AdventureWorks.Sales.SalesOrderHeader AS soh

We have this:

SELECT
    soh.SalesOrderID,
soh.OrderDate,
sod.max_unit_price,
sod.sum_line_total
FROM AdventureWorks.Sales.SalesOrderHeader AS soh
CROSS APPLY (
SELECT
max_unit_price = MAX(sod.UnitPrice),
sum_line_total = SUM(sod.LineTotal)
FROM Sales.SalesOrderDetail AS sod
WHERE soh.SalesOrderID = sod.SalesOrderID ) sod

As for the execution plans, in my experience CROSS APPLY has always won.  Not always by a lot, but it still wins.

So what is OUTER APPLY?  It’s equivalent to a left join on the derived table.

SELECT
soh.SalesOrderID,
soh.OrderDate,
sod.max_unit_price
FROM AdventureWorks.Sales.SalesOrderHeader AS soh
LEFT JOIN (
SELECT
max_unit_price = MAX(sod.UnitPrice),
      SalesOrderID
FROM Sales.SalesOrderDetail AS sod
   GROUP BY sod.SalesOrderID ) sod
ON sod.SalesOrderID = soh.SalesOrderID
SELECT
soh.SalesOrderID,
soh.OrderDate,
sod.max_unit_price
FROM AdventureWorks.Sales.SalesOrderHeader AS soh
OUTER APPLY (
SELECT
max_unit_price = MAX(sod.UnitPrice)
FROM Sales.SalesOrderDetail AS sod
WHERE soh.SalesOrderID = sod.SalesOrderID ) sod

Source:http://sqlserverplanet.com/sql-2005/cross-apply-explained

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: