Blog

posts tagged with winrt

Windows 8 Javascript Tips - TypeScript support

0 Comments
By Fons Sonnemans, 9-10-2012

Microsoft announced TypeScript last week. TypeScript is a superset of JavaScript that combines type checking and static analysis, explicit interfaces, and best practices into a single language and compiler. It is an open source programming language developed by Microsoft. If you haven't investigated yet make sure you do. The related links below might help you.

What Microsoft didn't do (yet) is add TypeScript support to JavaScript Windows Store apps. In this blog I will explain how to add this support to Visual Studio so you can use TypeScript in all your Windows 8 apps.

Step 1 - Install TypeScript

You can install TypeScript for Visual Studio 2012 using an MSI setup which you can download here. Make sure you first close all Visual Studio instances to avoid installation problems.

Step 2 - Install Web Essentials 2012

The latest version of Web Essentials 2012 extension adds support for TypeScript preview and compilation. When you save a TypeScript (.ts) file it will be compiled into a JavaScript (.js) file. So make sure you install it using the Visual Studio menu Tools, Extensions and Updates. If you already installed it make sure you update it to the latest version.

Step 3 - Add TypeScript ItemTemplate

If you try to add a TypeScript item to the 'js' folder you will see that there is no TypeScript template available. The setup from Microsoft did not (yet) add this template to Visual Studio. My solution for this problem was quite easy. I copied the following file 'C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\IDE\Extensions\msfz1qy5.oca\~IC\IT\CSharp\1033\f.zip' to my '\My Documents\Visual Studio 2012\Templates\ItemTemplates\JavaScript' folder. I also renamed the file to TypeScript.zip. Next I opened the zip file and edited the 'f.vstemplate' file. In the file I changed the ProjectType element from CSharp to JavaScript.

To make life easy you can download my TypeScript.zip file so you don't have to repeat my steps. Make sure you place it in the right ItemTemplate folder.

Step 4 - Create a JavaScript Project

This step is really easy. Just create a Project in Visual studio using one of the JavaScript Windows Store templates.

Step 5 - Add TypeScript item

When you add a new Item to the 'js' folder you can now select the TypeScript template.

The preview feature of Web Essentials 2012 shows you how your TypeScript file is compiled into JavaScript.

You should also change the Package Action of the Demo.ts file to 'None'. Otherwise the file will also be included in the APPX file which will make it larger. Only the Demo.js file is required.

TypeScript options

Web Essentials 2012 also supports some options which you might want to change. I only want to compile my TypeScripts on Build and not on every Save. You can also turn preview off but that didn't work on my computer. I hope they will fix it.

Closure

Now it is up to you to write your own TypeScript files. I love the ability to write clean OO code using: classes, interfaces, modules (namespaces), type annotations, compile time type checking and arrow functions (similar to Lambda Expression in C#). I hope this blog will help you write great Windows Store apps.

Cheers,

Fons

Related Links

Windows 8 XAML Tips - Detect App Deactivation

1 Comments
By Fons Sonnemans, 17-9-2012

Detecting when an Windows 8 Store app is deactivated isn't as easy as you would expect. In the Windows Phone project templates you get the Application_Launching(), Application_Activated(), Application_Deactivated() and Application_Closing() methods in the App.xaml.cs. But those methods don't exists in the Windows Store project templates. There is an OnSuspending() method but you can't use it to detect deactivation. You use it to store your data when suspending the app. This will problably go off a few seconds later than deactivation.

Solution

To solve this problem I have used the Activated event of the CoreWindow class. This event can also be used to detect deactivation inspite of it's name. The WindowActivatedEventArgs has a WindowActivationState property of the type CoreWindowActivationState. This enum holds the values CodeActivated, Deactivated and PointerActivated. This event also is fired when the app is closed.

Example

In the following example I have created an app in which a Timer updates a counter every second. In the constructor I have subscribed the page on the Activated event of the CoreWindow object using the GetForCurrentThread() method. The eventhandler stops the timer when the app is deactivead or closed. It restarts the timer when the app is activated again. The counter value is written to the LocalSettings on deactivation and close of the app. In the constructor of the MainPage the value is read from the LocalSettings so the app continues with the last used counter value.

public sealed partial class MainPage : Page {

    private DispatcherTimer _timer = new DispatcherTimer();
    private int _counter;
    private const string Key = "Counter";

    public MainPage() {
        this.InitializeComponent();

        this._timer.Interval = TimeSpan.FromSeconds(1);
        this._timer.Tick += _timer_Tick;

        object value;
        if (ApplicationData.Current.LocalSettings.Values.TryGetValue(Key, out value)) {
            _counter = (int)value;
            this.textBlockCounter.Text = _counter.ToString();
        }

        CoreWindow.GetForCurrentThread().Activated += MainPage_Activated;
    }

    void _timer_Tick(object sender, object e) {
        this._counter++;
        this.textBlockCounter.Text = _counter.ToString();
    }

    void MainPage_Activated(CoreWindow sender, WindowActivatedEventArgs args) {

        if (args.WindowActivationState == CoreWindowActivationState.Deactivated) {
            _timer.Stop();
            Windows.Storage.ApplicationData.Current.LocalSettings.Values[Key] = _counter;
        } else {
            _timer.Start();
        }
    }
}

The MainPage.xaml only contains a Grid and the TextBox which displays the counter value.

<Page
    x:Class="DetectAppDeactivation.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:DetectAppDeactivation"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
        <TextBlock x:Name="textBlockCounter"
                   Text="0"
                   FontSize="150"
                   VerticalAlignment="Center"
                   HorizontalAlignment="Center" />
    </Grid>
</Page>

Closure and download

I hope you like my solution. You can download my code here.

Cheers,

Fons

Windows 8 XAML Tips - Async Search Suggestions

3 Comments
By Fons Sonnemans, 22-8-2012

There are a lot of examples on the web how you can add Search Suggestions to the Search Charm of a Windows 8 Metro application. But all the examples I found only demonstrate how to implement a synchronous version. In this blog I will show you how you can do this also asynchronous. I use this technique to fill my Search Suggestion by calling a web service asynchronous. Something which is very common because your data will problably be stored in the Web/Cloud.

Implement Search Charm

To demonstrate the solution I created a new project in Visual Studio 2012 using the 'Grid App (XAML)' project template. Next I added the 'Search Contract' item template to the project. This adds an SearchResultsPage to the project and adds the Search Declaration to the Package.appxmanifest.

In my App.cs file I added the InitSearch() method which I call from the OnLaunched() method. In this InitSearch() method I subscribe the app on SuggestionsRequested event of the current SearchPane view.

sealed partial class App : Application
{
    /// <summary>
    /// Initializes the singleton Application object.  This is the first line of authored code
    /// executed, and as such is the logical equivalent of main() or WinMain().
    /// </summary>
    public App()
    {
        this.InitializeComponent();
        this.Suspending += OnSuspending;
    }

    /// <summary>
    /// Invoked when the application is launched normally by the end user.  Other entry points
    /// will be used when the application is launched to open a specific file, to display
    /// search results, and so forth.
    /// </summary>
    /// <param name="args">Details about the launch request and process.</param>
    protected override async void OnLaunched(LaunchActivatedEventArgs args)
    {
        // Do not repeat app initialization when already running, just ensure that
        // the window is active
        if (args.PreviousExecutionState == ApplicationExecutionState.Running)
        {
            Window.Current.Activate();
            return;
        }

        // Create a Frame to act as the navigation context and associate it with
        // a SuspensionManager key
        var rootFrame = new Frame();
        SuspensionManager.RegisterFrame(rootFrame, "AppFrame");

        if (args.PreviousExecutionState == ApplicationExecutionState.Terminated)
        {
            // Restore the saved session state only when appropriate
            await SuspensionManager.RestoreAsync();
        }

        if (rootFrame.Content == null)
        {
            // When the navigation stack isn't restored navigate to the first page,
            // configuring the new page by passing required information as a navigation
            // parameter
            if (!rootFrame.Navigate(typeof(GroupedItemsPage), "AllGroups"))
            {
                throw new Exception("Failed to create initial page");
            }
        }

        // Place the frame in the current Window and ensure that it is active
        Window.Current.Content = rootFrame;
        Window.Current.Activate();

        InitSearch();
    }

    private void InitSearch() {
        var view = SearchPane.GetForCurrentView();
        view.SuggestionsRequested += view_SuggestionsRequested;

        //view.QueryChanged += view__QueryChanged;
        //view.QuerySubmitted += view_QuerySubmitted;
        //view.ResultSuggestionChosen += view_ResultSuggestionChosen;
        //view.VisibilityChanged += view_VisibilityChanged;
    }

    private void view_SuggestionsRequested(SearchPane sender, 
                                    SearchPaneSuggestionsRequestedEventArgs args) {
        try {
            var list = Enumerable.Range(1, 4).Select(n => args.QueryText + " " + n);
            args.Request.SearchSuggestionCollection.AppendQuerySuggestions(list);
        } catch (Exception ex) {
            Debug.WriteLine(ex.Message);
        }
    }

In this example the SuggestionsRequested() method creates 4 query suggestions which are the querytext with the suffix 1 to 4. This will look like this if you run the app and start a search for the word 'demo'.

Problem

To simulate an async network call I added an awaited call to the Task.Delay() method in my view_SuggestionsRequested() method (line 5). I also added the async keyword to make the compiler happy. It is required if you use the await keyword.

private async void view_SuggestionsRequested(SearchPane sender, 
                                             SearchPaneSuggestionsRequestedEventArgs args) {
    try {
        // Simulate an async network call
        await Task.Delay(100);
        var list = Enumerable.Range(1, 4).Select(n => args.QueryText + " " + n);

        args.Request.SearchSuggestionCollection.AppendQuerySuggestions(list);
    } catch (Exception ex) {
        Debug.WriteLine(ex.Message);
        // A method was called at an unexpected time. (Exception from HRESULT: 0x8000000E)
    }
}

If I run the app the Search Suggestions don't work anymore. The catch blocks writes this message of the exception to the output window: 'A method was called at an unexpected time. (Exception from HRESULT: 0x8000000E)'.

Solution

The solution is quite simple but badly documented in the MSDN documentation of the SearchPane.SuggestionsRequested event. It states in a note that if you want to respond to this event asynchronously, you must use SearchPaneSuggestionsRequestedEventArgs.Request.GetDeferral. So in my code I retrieved the Deferral (line 5). And I called the Complete() method on it after the list is appended to the SearchSuggestionCollection (line 14).

private async void view_SuggestionsRequested(SearchPane sender,
                                             SearchPaneSuggestionsRequestedEventArgs args) {
    try {
        // Get the deferral
        var deferral = args.Request.GetDeferral();

        // Simulate an async network call
        await Task.Delay(100);
        var list = Enumerable.Range(1, 4).Select(n => args.QueryText + " " + n);

        args.Request.SearchSuggestionCollection.AppendQuerySuggestions(list);

        // Mark the deferral as Complete
        deferral.Complete();
    } catch (Exception ex) {
        Debug.WriteLine(ex.Message);
    }
}

This fixed the problem and my app runs like a charm ;-)

Closure and download

I hope you like my solution. You can download my code here.

Cheers,

Fons

Windows 8 XAML Tips - Settings Demo

0 Comments
By Fons Sonnemans, 10-8-2012

In my previous blog post I explained how you can use the PaneThemeTransition from the Animation Library to show a task pane. In this blog post I want to use this technique to open my Settings and About task panes from the Settings Charm. I will try to make it easier by introducing a TaskPanePopup helper class.

TaskPanePopup

You construct an instance of the TaskPanePopup class using a task pane, in most cases this will be a user control. In the constructor a Popup control is created and initialized with the Child (the task pane) and the ChildTransitions (PaneThemeTransition coming from the right). The Width of the task pane must be set to calculate the position of the Popup. The task pane will be shown in a Popup using the animation when you call the Show() method on the instance.

public class TaskPanePopup {

    private Popup _popup;
    public FrameworkElement TaskPane { get; private set; }

    public TaskPanePopup(FrameworkElement taskPane) {
        if (double.IsNaN(taskPane.Width)) {
            throw new ArgumentException("TaskPane width must be set");
        }
        this.TaskPane = taskPane;

        this._popup = new Popup {
            IsLightDismissEnabled = true,
            ChildTransitions = new TransitionCollection(),
            Child = taskPane,
        };

        this._popup.ChildTransitions.Add(new PaneThemeTransition {
            Edge = EdgeTransitionLocation.Right
        });
    }

    public void Show() {
        this.TaskPane.Height = Window.Current.Bounds.Height;
        this._popup.SetValue(
                Canvas.LeftProperty,
                Window.Current.Bounds.Width - this.TaskPane.Width
        );
        this._popup.IsOpen = true;
    }

}

Settings Charm

To demonstrate the use of my class I have created a sample appliation. This app must have a Settings and About command in the Settings Charm. Therefore I have subscribed the app on the CommandsRequested event of the current SettingsPane (line 30). In the event handler I have created two SettingsCommand objects and added them to the ApplicationCommands. These Commands create the TaskPanePopup objects in their handlers and shows them.

sealed partial class App : Application
{
    /// <summary>
    /// Initializes the singleton Application object.  This is the first line of authored code
    /// executed, and as such is the logical equivalent of main() or WinMain().
    /// </summary>
    public App()
    {
        this.InitializeComponent();
        this.Suspending += OnSuspending;
    }

    /// <summary>
    /// Invoked when the application is launched normally by the end user.  Other entry points
    /// will be used when the application is launched to open a specific file, to display
    /// search results, and so forth.
    /// </summary>
    /// <param name="args">Details about the launch request and process.</param>
    protected override async void OnLaunched(LaunchActivatedEventArgs args)
    {
        // Do not repeat app initialization when already running, just ensure that
        // the window is active
        if (args.PreviousExecutionState == ApplicationExecutionState.Running)
        {
            Window.Current.Activate();
            return;
        }

        // Init SettingsPane
        SettingsPane.GetForCurrentView().CommandsRequested += App_CommandsRequested;

        // Create a Frame to act as the navigation context and associate it with
        // a SuspensionManager key
        var rootFrame = new Frame();
        SuspensionManager.RegisterFrame(rootFrame, "AppFrame");

        if (args.PreviousExecutionState == ApplicationExecutionState.Terminated)
        {
            // Restore the saved session state only when appropriate
            await SuspensionManager.RestoreAsync();
        }

        if (rootFrame.Content == null)
        {
            // When the navigation stack isn't restored navigate to the first page,
            // configuring the new page by passing required information as a navigation
            // parameter
            if (!rootFrame.Navigate(typeof(GroupedItemsPage), "AllGroups"))
            {
                throw new Exception("Failed to create initial page");
            }
        }

        // Place the frame in the current Window and ensure that it is active
        Window.Current.Content = rootFrame;
        Window.Current.Activate();
    }

    private TaskPanePopup _settings;
    private TaskPanePopup _about;

    private void App_CommandsRequested(SettingsPane sender,
                                       SettingsPaneCommandsRequestedEventArgs args) {
            
        SettingsCommand cmd = new SettingsCommand("Settings", "Settings", (command) => {
            if (_settings == null) {
                _settings = new TaskPanePopup(new SettingsControl());
            }
            _settings.Show();
        });

        args.Request.ApplicationCommands.Add(cmd);

        cmd = new SettingsCommand("About", "About", (command) => {
            if (_about == null) {
                _about = new TaskPanePopup(new AboutControl());
            }
            _about.Show();
        });

        args.Request.ApplicationCommands.Add(cmd);
    }

If you start the application and open the Settings Charm (WinKey-I) you will get the following Settings Charm.

If you select the Settings command the SettingsControl will popup using the correct animation.

Task Pane User Control

A task pane is in my case a User Control with a back button, title and content. This content is shown using an EntranceThemeTransition from the Animation Library. This will bring this app to life.

XAML of my SettingsControl user control

<UserControl
    x:Class="SettingsDemo.SettingsControl"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:SettingsDemo"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    d:DesignHeight="768"
    Width="350">

    <Grid
        Background="Crimson">
        <Grid.ColumnDefinitions>
            <ColumnDefinition
                Width="45" />
            <ColumnDefinition />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition
                Height="100" />
            <RowDefinition />
        </Grid.RowDefinitions>
        <Grid
            VerticalAlignment="Bottom"
            Grid.Column="1">
            <Grid.ColumnDefinitions>
                <ColumnDefinition
                    Width="Auto" />
                <ColumnDefinition />
            </Grid.ColumnDefinitions>
            <Button
                Click="ButtonBack_Click"
                HorizontalAlignment="Stretch"
                Margin="0"
                Style="{StaticResource SnappedBackButtonStyle}"
                VerticalAlignment="Bottom" />
            <TextBlock
                Text="Settings"
                Grid.Column="1"
                VerticalAlignment="Top"
                Style="{StaticResource SubheaderTextStyle}"
                FontFamily="Segoe UI Semibold" />
        </Grid>
        <StackPanel
            Grid.Row="1"
            Grid.Column="1">
            <StackPanel.ChildrenTransitions>
                <TransitionCollection>
                    <EntranceThemeTransition
                        FromHorizontalOffset="100" />
                </TransitionCollection>
            </StackPanel.ChildrenTransitions>
            <TextBlock
                TextWrapping="Wrap"
                Text="Place your content here"
                Style="{StaticResource BasicTextStyle}" />
        </StackPanel>
    </Grid>
</UserControl>

C# code behind of my SettingsControl user control

public sealed partial class SettingsControl : UserControl {

    public SettingsControl() {
        this.InitializeComponent();
    }

    private void ButtonBack_Click(object sender, RoutedEventArgs e) {
        var popup = this.Parent as Popup;
        if (popup != null) popup.IsOpen = false;
        SettingsPane.Show(); 
    } 
}

Closure

I hope you like my solution. You can download my code below.

Cheers,

Fons

Windows 8 XAML Tips - Show a task pane

1 Comments
By Fons Sonnemans, 25-6-2012

You can integrate the look and feel introduced in Windows 8 Release Preview into your Metro style app by using the Animation Library suite of Windows-provided animations. Use of the Animation Library animations provides these benefits:

  • Motions that align to Metro style animation principles
  • Fast, fluid transitions between UI states that inform but do not distract the user
  • Clearer visuals to show the user transitions within an app

One of the animations that are supplied in the Animation Library is the show hide panel animation. You use it to show and hide a panel, which is large edge-based UI such as a custom keyboard or a task pane. This 'Windows Animation (Metro styled apps)' article shows you how you can use the PaneThemeTransition animation class in XAML. The article also contains the video below in which the animation is shown. Sadly there is no code sample how to use it in your XAML/C# application. With this blog I want to fill in the gap. I will explain you how you get the animation as shown in the video.

Show a task pane video

If you play this video you will see a task plane appear from the right side of the screen.

My Solution

In my solution I have a page with only one button. If you click this button a red Rectangle will appear from the right side of the screen. You can off course replace this Rectangle with your own User Control.

I use a Popup control to show my red Rectangle with a with of 300 pixels. The Child property of the Popup is set to the Rectangle. The Popup has a ChildTransitions which is filled with a PaneThemeTransition animation object. The PaneThemeTransition object has a Edge property set to the Right. The left position of the Popup is calculated using the actual width of the page minus the width of the rectangle. This position and the height of the Rectangle are set every time the pane is shown because it can differ due to view changes (filled, landscape, portrait).

public sealed partial class MainPage : Page {

    private Popup _popup;

    public MainPage() {
        this.InitializeComponent();
    }

    private void ButtonShow_Click(object sender, RoutedEventArgs e) {
        ShowTaskPane();
    }

    /// <summary>
    /// Show and hide a task pane or other large UI container from the edge of the screen.
    /// http://msdn.microsoft.com/en-US/library/windows/apps/hh975420
    /// </summary>
    private void ShowTaskPane() {
        const int width = 300;

        if (_popup == null) {

            var rect = new Rectangle {
                Fill = new SolidColorBrush(Colors.Red),
                Width = width,
            };

            _popup = new Popup {
                IsLightDismissEnabled = true,
                ChildTransitions = new TransitionCollection(),
                Child = rect,
            };

            _popup.ChildTransitions.Add(new PaneThemeTransition 
                                        { Edge = EdgeTransitionLocation.Right });
        }

        (_popup.Child as FrameworkElement).Height = this.ActualHeight;
        _popup.SetValue(Canvas.LeftProperty, this.ActualWidth - width);
        _popup.IsOpen = true;
    }
}

Closure

I hope you like my solution. I my next blog I will try to create a more generic one. I will then use it to show task panes from the Settings charm.

Cheers,

Fons

Windows 8 XAML Tips – Custom Fonts

1 Comments
By Fons Sonnemans, 12-6-2012

It is time for me to write a series of blog items on writing XAML applications for Windows 8. I plan to write one every two weeks. I hope I can keep up the promise.

Custom Fonts

I have developed XAML applications in Silverlight (Browser and Phone) for a couple of years. I used custom fonts in those Apps using Expression Blend. It contains a Font Manager which you can use to embed a font into the application (project/assembly). Blend for Visual Studio doesn’t allow you to use the Font Manager. The menu option is disabled in this Release Candidate. I hope to get it back in a future version.

The default FontFamily in a Metro app is ‘Segoe UI’ which is called ‘Global User Interface’ in Blend. You can of course use Blend or Visual Studio to select another FontFamily. But if your user doesn’t have this font installed you will get the default font. That’s why you will have to add the font to the application.

Luckily it is possible to add it to the application manually. For this demo I will be using a free true type font called 123Sketch which I downloaded here: http://www.dafont.com/123sketch.font. First I created a new folder in my project named ‘Fonts’. I added my font file to this folder. The Build Action for the file is set to ‘Content’ which is required.

123Sketch.ttf added to the Fonts folder

You reference the font file and font name in your XAML using the following format:
FontFamily="/<path to font file>/<font file>#<font name>"

So in my case a TextBlock would be defined like this.

<TextBlock
    Text="Hello World"
    FontSize="45"
    FontFamily="/Fonts/123Sketch.ttf#123Sketch" />

FontFamily Resource

It is smart to create a Resource for this FontFamily property. This will make it easier for you if you want to change the font for another one. In Blend you can convert the FontFamily by clicking on the white square next to the dropdown.

Convert FontFamily to New Resource

You will get a dialog in which you can set the name (key) of the resource and the location where it will be defined. In this demo I named it ‘MyCustomFont’ and defined it in ‘This Document’. Choosing the ‘Application’ or a ‘Resource Dictionary’ would make this resource reusable in other documents.

Create FontFamily Resource

You can now use the resource for the FontFamily property in other elements. Just pick it from the ‘Local Resource’.

Assign Local Resource

Result

The XAML of the Page including the static resource and two TextBlock elements would look like this.

<Page
    x:Class="FontDemo.MainPage"
    IsTabStop="false"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:FontDemo"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <Page.Resources>
        <!-- TODO: Move the next line to App.xaml or a ResourceDictionary -->
        <FontFamily            
            x:Key="MyCustomFont">/Fonts/123Sketch.ttf#123Sketch</FontFamily>
    </Page.Resources>

    <Grid
        Background="{StaticResource ApplicationPageBackgroundThemeBrush}">

        <TextBlock
            HorizontalAlignment="Left"
            Margin="65,48,0,0"
            TextWrapping="Wrap"
            Text="Hello"
            VerticalAlignment="Top"
            FontSize="45"
            FontFamily="{StaticResource MyCustomFont}" />

        <TextBlock
            HorizontalAlignment="Left"
            Margin="65,118,0,0"
            TextWrapping="Wrap"
            Text="World"
            VerticalAlignment="Top"
            FontSize="45"
            FontFamily="{StaticResource MyCustomFont}" />

    </Grid>
</Page>

If you start the application in the Simulator you get this result.

Simulator showing the result

I hope this helps you. Fonts often are copyright protected. So if you want to add one make sure you have the rights or use a free one.

Cheers,

Fons

Windows 8 DevCamp sessies

0 Comments
By Fons Sonnemans, 26-4-2012

Op 12 en 13 april 2012 heeft Microsoft Nederland in de Fabrique in Maarssen het Windows 8 Developer & User Experience Design Camp georganiseerd. Het was een druk bezocht evenement waarbij er een bijna 50/50 mix was van developers en designers.

De eerste dag bestond uit een programma van sessies, waarbij er ook breakouts waren voor developers en voor designers. Hiervan heb ik 2 sessies mogen verzorgen. Deze sessies zijn opgenomen en staan nu online op Channel9.

Het bouwen van een Metro style app

Deze sessie laat zien hoe met XAML, C# en WinRT een Metro style applicatie voor Windows 8 gebouwd kan worden. Er wordt getoond wat de veranderingen en toevoegingen zijn in Windows 8. Denk hierbij aan asynchroon programmeren en andere technieken die de kwaliteit van Metro style apps zullen verhogen.

Laat je Metro style app leven door tiles en notificaties

Gebruikers worden als het ware naar een app toegetrokken door het gebruik van actieve tiles op het start scherm. Notificaties die door de Windows Push Notification Service verstuurd kunnen worden, kunnen gebruikers weer de aandacht vestigen op een app zonder dat die actief is. In deze sessie wordt verteld hoe tiles en notificaties gebruikt kunnen worden. Er wordt ook geleerd hoe een tile een deep link naar specifieke informatie in een app kan verzorgen

Overige sessies

Cheers,

Fons

MessageBox.Show() in WinRT

6 Comments
By Fons Sonnemans, 12-3-2012

I'm currently in the process of converting some of my Windows Phone apps to the Windows 8 Consumer Preview. While doing so I discovered there is no MessageBox.Show() method in WinRT. The alternative is to use the new MessageDialog class. This means I have to rewrite a lot of code which I try to avoid. Therefore I came up with my own MessageBox helper class which mimics the behavior of the WP7 MessageBox. In this post I will demonstrate this, using the following sample application.

Suppose I have the following code in my Windows Phone application:

private void Button1_Click(object sender, RoutedEventArgs e) {
    var result = MessageBox.Show("This is MessageBox", "Title", MessageBoxButton.OKCancel);
    if (result == MessageBoxResult.OK) {
        // do something    
    }
    Button1.Content = result.ToString();
}

In Windows 8 I would have to rewrite it to the following:

private async void Button1_Click(object sender, RoutedEventArgs e) {
    MessageDialog md = new MessageDialog("This is a MessageDialog", "Title");
    bool? result = null;
    md.Commands.Add(
       new UICommand("OK", new UICommandInvokedHandler((cmd) => result = true)));
    md.Commands.Add(
       new UICommand("Cancel", new UICommandInvokedHandler((cmd) => result = false)));

    await md.ShowAsync();
    if (result == true) {
        // do something    
    }
    Button1.Content = result.ToString();
}

As you can see I have marked the Button1_Click() method with the async keyword. This is necessary because the ShowAsync() method is called, using the new await keyword. The MessageDialog is shown in an seperate thread which will allow the main thread to continue to execute. This allows all animations running on the main thread to continue to play.

My MessageBox show helper class makes my conversion much easier. You only have to change the Show() call to a ShowAsync() call and add the await and async keywords.

private async void Button2_Click(object sender, RoutedEventArgs e) {
    var result = await MessageBox.ShowAsync("This is a MessageBox", 
                                            "Title", MessageBoxButton.OKCancel);
    if (result == MessageBoxResult.OK) {
        // do something    
    }
    Button2.Content = result.ToString();
}

Here is the code of my MessageBox helper class:

using System;
using System.Threading.Tasks;
using Windows.UI.Popups;

namespace ReflectionIT.Windows8.Helpers {

    class MessageBox {

        public static async Task<MessageBoxResult> ShowAsync(string messageBoxText, 
                                                             string caption, 
                                                             MessageBoxButton button) {

            MessageDialog md = new MessageDialog(messageBoxText, caption);
            MessageBoxResult result = MessageBoxResult.None;
            if (button.HasFlag(MessageBoxButton.OK)) {
                md.Commands.Add(new UICommand("OK", 
                    new UICommandInvokedHandler((cmd) => result = MessageBoxResult.OK)));
            }
            if (button.HasFlag(MessageBoxButton.Yes)) {
                md.Commands.Add(new UICommand("Yes", 
                    new UICommandInvokedHandler((cmd) => result = MessageBoxResult.Yes)));
            }
            if (button.HasFlag(MessageBoxButton.No)) {
                md.Commands.Add(new UICommand("No", 
                    new UICommandInvokedHandler((cmd) => result = MessageBoxResult.No)));
            }
            if (button.HasFlag(MessageBoxButton.Cancel)) {
                md.Commands.Add(new UICommand("Cancel", 
                    new UICommandInvokedHandler((cmd) => result = MessageBoxResult.Cancel)));
                md.CancelCommandIndex = (uint)md.Commands.Count - 1;
            }
            var op = await md.ShowAsync();
            return result;
        }

        public static async Task<MessageBoxResult> ShowAsync(string messageBoxText) {
            return await MessageBox.ShowAsync(messageBoxText, null, MessageBoxButton.OK);
        }
    }

    // Summary:
    //     Specifies the buttons to include when you display a message box.
    [Flags]
    public enum MessageBoxButton {
        // Summary:
        //     Displays only the OK button.
        OK = 1,
        // Summary:
        //     Displays only the Cancel button.
        Cancel = 2,
        //
        // Summary:
        //     Displays both the OK and Cancel buttons.
        OKCancel = OK | Cancel,
        // Summary:
        //     Displays only the OK button.
        Yes = 4,
        // Summary:
        //     Displays only the Cancel button.
        No = 8,
        //
        // Summary:
        //     Displays both the OK and Cancel buttons.
        YesNo = Yes | No,
    }

    // Summary:
    //     Represents a user's response to a message box.
    public enum MessageBoxResult {
        // Summary:
        //     This value is not currently used.
        None = 0,
        //
        // Summary:
        //     The user clicked the OK button.
        OK = 1,
        //
        // Summary:
        //     The user clicked the Cancel button or pressed ESC.
        Cancel = 2,
        //
        // Summary:
        //     This value is not currently used.
        Yes = 6,
        //
        // Summary:
        //     This value is not currently used.
        No = 7,
    }
}

I have also added the 'Yes' and 'No' Buttons to the MessageBoxButton enum. This is something I was always missing in the Windows Phone API. Now you can not only use OK/Cancel but also Yes/No/Cancel.

private async void Button3_Click(object sender, RoutedEventArgs e) {
    var result = await MessageBox.ShowAsync("This is a MessageBox", "Title", 
                                            MessageBoxButton.YesNo | MessageBoxButton.Cancel);
    if (result == MessageBoxResult.Yes) {
        // do something    
    }
    if (result == MessageBoxResult.No) {
        // do something    
    }
    Button3.Content = result.ToString();
}

Download my sample project which contains all source code.

Cheers,

Fons

Sudoku running on a WP7 Device

0 Comments
By Fons Sonnemans, 9-8-2010

My Sudoku is running on a Samsung Windows Phone 7 device!

Tags: Windows 8, WinRT

All postings/content on this blog are provided "AS IS" with no warranties, and confer no rights. All entries in this blog are my opinion and don't necessarily reflect the opinion of my employer or sponsors. The content on this site is licensed under a Creative Commons Attribution By license.