31 Days of Windows 8 | Day #17: The Clipboard

This article is Day #17 in a series called 31 Days of Windows 8.  Each of the articles in this series will be published for both HTML5/JS and XAML/C#. You can find additional resources, downloads, and source code on our website.

advertisementsample

Today, we’re going to focus on the Windows 8 clipboard exclusively. More specifically, we’re going to look at how we can save and retrieve data from this system-wide and heavily used mechanism.  There are generally four types of data that we are going to see a user want to copy and paste:

  • Text
  • HTML
  • Images
  • Files

We’ll write some code in this article that shows not only how to copy and paste these values, but also how to detect which type of data the clipboard currently contains.

Saving Data to the Clipboard

As we saw briefly in yesterday’s article on context menus, we took a very quick look at saving some text to the clipboard.  This time, we’ll cover that in more depth, and include saving images and files to the clipboard as well.  To get started, we should talk about the DataPackage object.

A DataPackage is what we are going to use to transport our data.  We will create a DataPackage when we save data to the clipboard, and we will use the Clipboard.GetContent() method to retrieve the data when we’re pasting it.

In my sample project (which you can download from GitHub), you will see that I’ve created a button with an event handler for each data type.  We’ll spend the rest of this section looking at how we store these different types of data to the Clipboard.

It is important to note that the clipboard is actually divided into several sections, one for each data type.  You can save data to one or many of these sections, and the target for pasting will make the determination as to what type of data it will display when pasted.  This might sound very similar to how the Share Contract works, and for the most part, it is.

It’s also likely that you’ve encountered this in the past: you copy content from one app, and try to paste it in another, only to have it paste something else.  This is a direct artifact of the “sections” of the clipboard.  Let’s take a look at how to save each data type:

Text

Certainly the simplest example, text can be stored to the Clipboard in three lines of code:

DataPackage d = new DataPackage();
d.SetText(TextBoxValue.Text);
Clipboard.SetContent(d);
 

You will see a pattern form as we move through the other examples, but this is about as basic as they come.  We create a new DataPackage object, call the SetText() method with the text we want to save, and then set the content of the Clipboard to that DataPackage.

HTML

HTML, while similar to text, has its own quirks and formatting, and because of this, requires slightly different treatment when adding it to a DataPackage.  In this example, I am grabbing the HTML source from a WebView control (HTMLSource), and using that as my DataPackage contents.  However, I am also setting the SetText() value of this DataPackage, so that you can see how multiple values can be set at the same time.

DataPackage d = new DataPackage();
            
string s = HtmlFormatHelper.CreateHtmlFormat(HTMLSource.InvokeScript("eval", new string[] { "document.documentElement.outerHTML;" }));
d.SetHtmlFormat(s);
 
string t = HtmlUtilities.ConvertToText(s);
d.SetText(t);
 
Clipboard.SetContent(d);

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

As you can see above, we can set multiple values at the same time, and as you get deeper into this example, you’ll start to notice that most of your favorite apps store data in multiple formats “just in case.”

Images

Our next example is images, and I want to be really clear on this one.  We’re not talking about a file that happens to be an image.  We’re talking about copying an image from a website, for example, and then pasting it into a OneNote file or Windows Live Writer.  In my example, I am allowing the user to copy an image from my application to their clipboard.

DataPackage d = new DataPackage();
Uri uri = new Uri("ms-appx:///Assets/WideLogo.png");
StorageFile sf = await StorageFile.GetFileFromApplicationUriAsync(uri);
d.SetBitmap(RandomAccessStreamReference.CreateFromFile(sf));
Clipboard.SetContent(d);
 

In the image example, we are grabbing the image from its location in our project, creating a StorageFile from it, and then setting the SetBitmap() content of the DataPackage with it.  As with all of the examples in this article, we end our code with Clipboard.SetContent() to actually complete the action.

Files

Files are treated very similarly to images, but there’s one major difference: we can copy multiple files to the clipboard at once.  You’ve done this before, highlight and grab some of the files cluttering up your desktop before dragging them as a group to the Recycle Bin.  Instead of throwing them away, you could cut/copy them, and paste them to another location.  Files are always passed as a collection of files, even if there is only one.

DataPackage d = new DataPackage();
Uri uri = new Uri("ms-appx:///Assets/PeriodicTable.xls");
List<StorageFile> files = new List<StorageFile>();
StorageFile sf = await StorageFile.GetFileFromApplicationUriAsync(uri);
files.Add(sf);
d.SetStorageItems(files);
Clipboard.SetContent(d);
 

As you can see, there’s very little difference between the code for images and files.  One important note, as you work through this in your own project, relates to files you might add to your project.  When I added the PeriodicTable.xls file to my project, I initially forgot to set the “Build Action” on that file in my project, and by default, the Build Action is “None.”  If you also forget, using the code above will result in a “FileNotFoundException.”

Simply set the Build Action of your file to “Content” by looking in the Properties pane of Visual Studio 2012.

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }17-XAML-BuildAction

So, as far as saving content to the Clipboard, that’s just about it!  Our next step is going to be retrieving it from the Clipboard when the user chooses to paste it.

Detecting the Contents of the Clipboard

When it comes to “getting pasted” as I’ve started saying, I tend to do this all in one method that gets the content, determines which data type is available, and displays the content correctly based on that determination.

I had hoped, when writing this article, that there was going to be some amazing event handler, like OnPastedTo() or something, that would recognize when the user is attempting to paste some content to the app, so that we can take action on it.  (I personally live and die with Ctrl + X, Ctrl + C, and Ctrl + V).  I have not found that event yet, but if/when I do, I will update this page.  For now, I’ve created my own event handler that fires when you click a button.

You’ll see, in the example below, that I call the GetContent() method on the Clipboard, and then use a series of IF statements to act on the content appropriately.

private async void PasteButton_Click(object sender, RoutedEventArgs e)
{
    var DataPackage = Clipboard.GetContent();
 
    if (DataPackage.Contains(StandardDataFormats.Text))
    {
        TextBoxPaste.Text = await DataPackage.GetTextAsync();
    }
 
    if (DataPackage.Contains(StandardDataFormats.Bitmap))
    {
        RandomAccessStreamReference image = await DataPackage.GetBitmapAsync();
        var imageStream = await image.OpenReadAsync();
        BitmapImage bmp = new BitmapImage();
        bmp.SetSource(imageStream);
        ImagePaste.Source = bmp;
    }
 
    if (DataPackage.Contains(StandardDataFormats.StorageItems))
    {
        var storageFiles = await DataPackage.GetStorageItemsAsync();
 
        foreach (var file in storageFiles)
        {
            var currentFile = file as StorageFile;
            await currentFile.CopyAsync(ApplicationData.Current.LocalFolder, currentFile.Name, NameCollisionOption.ReplaceExisting);
            MessageText.Text = currentFile.Name + " has been saved to " + ApplicationData.Current.LocalFolder.Path.ToString() + "/" + currentFile.Name;
        }
    }
 
    if (DataPackage.Contains(StandardDataFormats.Html))
    {
        string html = await DataPackage.GetHtmlFormatAsync();
        HTMLPaste.NavigateToString(html);
    }
}

 

Let me quickly discuss each of the IF statements.  For text, I simply grab the Text data and place it in a TextBlock control on my page.  For an image, I need to convert the Image data to a BitmapImage object before I can set it as the source of an Image control.  For files, I loop through the collection of files, saving each of them as local files in my application, and then write the name of the file and the location of the folder to a TextBlock.  Finally, for HTML, I grab the HTML source, and, using a WebView control, navigate the control to the HTML source that I have received.

In all it’s pretty simple, but I was delighted the first time that I copied content from a webpage directly into my app, and it just worked!  The same is true for images, text, and files.  I highly recommend grabbing the source of this project and playing with it.  It will really help you to understand exactly how the clipboard is being used by your other applications.

Summary

Today, we took a deep look at the Clipboard, and how we can save and retrieve data as needed.  It supports several different file types, and I think you’ll be surprised just how redundant most of your favorite applications are when they save data to the Clipboard.

To download the entire code solution for the project discussed in this article, click the icon below:

downloadXAML

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

Tomorrow, we’re going to add another useful tool to our Windows 8 development tool belt: the FilePicker.  We’ll look at retrieving files from the user’s device, and even filtering them so that we only get our preferred file types.  See you then!

downloadTheTools

31 Days of Windows 8 | Day #16: Context Menus

This article is Day #16 in a series called 31 Days of Windows 8.  Each of the articles in this series will be published for both HTML5/JS and XAML/C#. You can find additional resources, downloads, and source code on our website.

advertisementsample

Today, our focus is on context menus.  These are those small little popup commands that appear from time to time in your application when you right click on something. Microsoft offers some very specific guidance on when to use these context menus vs. when to use the AppBar control instead, so we will be following those rules in this article. 

What Is a Context Menu?

If you’ve used Windows 8 at all, you’ve likely encountered these before.  Often they result from a right-click on something you couldn’t select, or on text you wanted to interact with.  Here’s a quick sample of a context menu:

An image of the context menu for text shown over editable text while there is no text in the clipboard to paste.

(image from http://msdn.microsoft.com/library/windows/apps/Hh465308)

You could also launch a context menu from an element on your page that is unselectable, like this image in my sample app:

16-XAML-ContextMenuExample

Right-clicking the image launches the context menu to the right.  (I will show you how to make this happen next.)  Each of the command items will have an action assigned to it, which is executed when the item is clicked.

Determining The Location of an Element

You may have noticed that context menus appear directly adjacent to the element that has been selected.  This doesn’t happen by magic.  We’ll actually have to determine the position of the clicked element by ourselves (as well as its size), and pass that to our Popup menu control when we create it in the form of a Rect object.  Here’s the method I’ve created to determine this location:

private Rect GetRect(object sender)
{
    FrameworkElement element = sender as FrameworkElement;
    GeneralTransform elementTransform = element.TransformToVisual(null);
    Point point = elementTransform.TransformPoint(new Point());
    return new Rect(point, new Size(element.ActualWidth, element.ActualHeight));
}
 

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

As you can see, I will be able to pass my “sender” object into this method, and return a Rect object with a point (the location of the top left corner of our element) and size (the dimensions of our calling object.)

Creating a Context Menu

Once I have this GetRect() method in place, creating a context menu around any of my controls is simple.  In this example, I have added a RightTapped event to my image, which calls this method:

private async void Element_RightTapped(object sender, RightTappedRoutedEventArgs e)
{
    PopupMenu p = new PopupMenu();
    p.Commands.Add(new UICommand("31 Days of Windows 8", (command) =>
        { ((Grid)Logo.Parent).Background = new SolidColorBrush(Colors.Orange); }));
    await p.ShowForSelectionAsync(GetRect(sender), Placement.Right);
}
 

As you can see above, this simply creates a new PopupMenu control, adds a command to it (with the executing code specified in the lambda expression), and calls the ShowForSelectionAsync() method to show it.  This method takes two parameters:

  • The first is the Rect value that we are retrieving from our GetRect() method.  Pass the sender in, get the appropriate Rect in return.
  • The second is the placement of the context menu.  In my example, I set Placement.Right as my value.  You have four options, but don’t go crazy with this.  Microsoft’s guidance on context menus is that “they should appear above the object they are acting upon, unless it obscures other UI elements, in which case, moving it to the side or below the object is acceptable.”  Keep the experience in Windows 8 consistent for your users unless you have a good reason to do otherwise.

Running this code, as shown above, will result in a menu that looks like this:

16-XAML-ContextMenuRight

And when I execute that option, the background of the page turns orange.  Like this:

16-XAML-ContextMenuRightLight

So, that’s how we pop a context menu.  But how many commands can we have at once?  The answer is SIX.  Adding more than 6 elements to your PopupMenu control will result in an error when you try to create it.  I showed it earlier, but here’s an example of a 6 element menu:

16-XAML-ContextMenuExample

Finally, you also have the option to create a UICommandSeparator(), which is simply a horizontal line instead of a command.  Separators still take up one of your 6 available slots, however, so keep this in mind when using it.  It looks like this:

16-XAML-ContentSeparator

To do this, your command creation statement would look like this:

p.Commands.Add(new UICommand("31 Days of Windows 8", (command) => { ((Grid)Logo.Parent).Background = new SolidColorBrush(Colors.Orange); }));
p.Commands.Add(new UICommandSeparator());
 

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

 

That’s about it!  You should now be able to add contextual menus to your applications when AppBars and other UI don’t make sense.  But what about interacting with just some of the text in a TextBox?

Launching a Context Menu From a TextBox

Actually, nearly everything about this process is the same, except for the math on where to pop the box from.  Initially when setting out to solve this problem, I was hoping to add on to the existing context menu that already appears when you right-click on text:

16-XAML-TextMenuDefault

As it turns out, you can’t.  So, for our example, let’s say that we want to keep all of those options, but also add a new one titled “Delete” at the bottom.  To do this, we first need to override the default context menu by creating an event handler to cancel the default one, and then recreate all of the functionality of the old one.

To do this, we create a new event handler like this:

protected override void OnNavigatedTo(NavigationEventArgs e)
{
    Lipsum.ContextMenuOpening += Lipsum_ContextMenuOpening;
}
 
protected override void OnNavigatingFrom(NavigatingCancelEventArgs e)
{
    Lipsum.ContextMenuOpening -= Lipsum_ContextMenuOpening;
}
 

I also created a statement to remove this event handler when we leave the page.

In the method that this event handler calls, we will cancel the initial call with Handled = true, and then create our own context menu that still makes all of the appropriate calls to the clipboard.  We are only going to briefly cover using the Clipboard in this article, but we will spend the entire article tomorrow on the different ways to use this great tool.

In addition, finding the right place to pop a context menu inside of a TextBox is different than just determining the position of a control on the page.  Here’s my GetTextBoxRect() method:

private Rect GetTextBoxRect(TextBox t)
{
    Rect temp = t.GetRectFromCharacterIndex(t.SelectionStart, false);
 
    GeneralTransform transform = t.TransformToVisual(null);
    Point point = transform.TransformPoint(new Point());
    point.X = point.X + temp.X;
    point.Y = point.Y + temp.Y;
 
    return new Rect(point, new Size(temp.Width, temp.Height));
}

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

And here’s the method for creating our PopupMenu control (you’ll notice that I used a secondary method for determining which command is tapped that doesn’t use lambdas this time.  It makes for easier readability, but you should also notice the method is much, much longer.)

async void Lipsum_ContextMenuOpening(object sender, ContextMenuEventArgs e)
        {
            e.Handled = true;
            TextBox t = (TextBox)sender;
 
            PopupMenu p = new PopupMenu();
            p.Commands.Add(new UICommand("Cut", null, 0));
            p.Commands.Add(new UICommand("Copy", null, 1));
            p.Commands.Add(new UICommand("Paste", null, 2));
            p.Commands.Add(new UICommand("Select All", null, 3));
            p.Commands.Add(new UICommandSeparator());
            p.Commands.Add(new UICommand("Delete", null, 4));
 
            var selectedCommand = await p.ShowForSelectionAsync(GetTextBoxRect(t));
 
            if (selectedCommand != null)
            {
                String text;
                DataPackage d;
                
                switch ((int)selectedCommand.Id)
                {
                    case 0: //CUT
                        text = t.SelectedText;
                        t.SelectedText = "";
                        d = new DataPackage();
                        d.SetText(text);
                        Clipboard.SetContent(d);
                        break;
                    case 1: //COPY
                        text = t.SelectedText;
                        d = new DataPackage();
                        d.SetText(text);
                        Clipboard.SetContent(d);
                        break;
                    case 2: //PASTE
                        text = await Clipboard.GetContent().GetTextAsync();
                        t.SelectedText = text;
                        break;
                    case 3: //SELECT ALL
                        t.SelectAll();
                        break;
                    case 4: //DELETE
                        t.SelectedText = "";
                        break;
                }
            }
        }
 

If you’re following along in your own project, you should now be able to highlight some text in your TextBox, and get a menu that looks like this one:

16-XAML-FinalTextBox

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

Summary

Today we looked at the art of creating inline context menus for our users.  They are an excellent way to provide interactions with elements that aren’t selectable, or for commands that make more sense directly adjacent to the element being interacted with.

If you would like to see the entire code sample from this article, click the icon below:

downloadXAML

Tomorrow, as promised, we will venture further into the Clipboard functionality available to us in Windows 8 development.  See you then!

downloadTheTools

31 Days of Windows 8 | Day #15: The On-Screen Keyboard

This article is Day #15 in a series called 31 Days of Windows 8.  Each of the articles in this series will be published for both HTML5/JS and XAML/C#. You can find additional resources, downloads, and source code on our website.

advertisementsample

Today we are going to take a look at the on-screen keyboard in Windows 8.  Microsoft does not seem to make a distinction in naming between the keyboard that appears when you tap your finger on a TextBox control and the one that can be found in the Ease of Access Center.  We are going to focus today on the keyboard that looks like this:

15-XAML-NormalKeyboard

The Ease of Access On-Screen Keyboard, on the other hand, is a tool designed for making a computer easier to use for those that may not be able to use a keyboard at all.  It can be found by opening the Ease of Access center on your machine…

15-XAML-EaseOfAccessCenter

And clicking the “Start On-Screen Keyboard” option.  You will discover a keyboard that looks like this, instead:

15-XAML-EaseOfAccessKeyboard

The primary focus of this keyboard is to allow a user to completely use Windows without having a keyboard attached to their computer.  It’s not customizable, and doesn’t respond to any of the code we are going to write in this article.  This keyboard is also one of the only windows that can be placed over the Start Screen.  Check this out:

15-XAML-OnScreenKeyboardStartScreen

 

OK, so I’ve spent the first few paragraphs of this article talking about a keyboard that is NOT the focus of this article.  Why?  There are two reasons:

  1. If you are using a non-touch device when you work through this article (or on your own app and want to use the features of the regular touch keyboard), you’ll find that mouse clicks don’t launch the touch keyboard on your machine.  So you’ll search the web looking for a solution to make it show up.
  2. As you search around the web looking for more information about manipulating the on-screen keyboard in Windows 8, you’re going to get plenty of articles on the Ease of Access one, which is likely not what you wanted. If you do find an appropriate article about how to turn on the touch keyboard, it’s likely this one, because I wasn’t able to find any way to make this work.

The primary reason for this is because this is one of the few times that Windows 8 makes a distinction between a mouse click and and finger tap.  If you mouse click on a TextBox, Windows 8 assumes you are using a real keyboard, even if you’re using a touch-enabled machine.  A finger-tap, however, will produce that keyboard we’re going to talk about today.

To save you some frustration, when developing your application that will take advantage of the on-screen keyboard, use the simulator if you’re not working on a touch machine.  It allows you to simulate “taps” with your mouse.  Here’s where you set it:

15-XAML-SimulatorTapButton

OK, now that we’ve gotten all that out of the way, let’s get this actual article started.

Using the On-Screen Keyboard

First, let’s take a look at the default states of the on-screen keyboard that the user can navigate to any time the keyboard is open.  We saw the standard QWERTY view earlier:

15-XAML-NormalKeyboard

But there are several more.  When we build an application, our primary focus, above all else, should be to make the tasks a user needs to accomplish as easy as possible.  (That IS on the top of your mind, right?)  To that end, the on-screen keyboard can be manipulated to make that happen.  There is a property that can be set on TextBox controls called InputScope that allows us to pop the appropriate keyboard for the task at hand.  If an InputScope is not specified, the normal keyboard will be displayed.  Here’s what the code looks like:

<TextBox InputScope="EmailSmtpAddress" />
 

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

You will find, as you start playing with InputScope, that there are actually 18 different InputScope values that can be used (but for English-speaking users, there’s really only three different keyboards at this time).  They are (in alphabetical order):

  • AlphanumericFullWidth
  • AlphaNumericHalfWidth
  • ChineseFullWidth
  • ChineseHalfWidth
  • Default
  • EmailSmtpAddress
  • HangulFullWidth
  • HangulHalfWidth
  • Hanja
  • Hiragana
  • KatakanaFullWidth
  • KatakanaHalfWidth
  • NativeScript
  • Number
  • NumberFullWidth
  • Search
  • TelephoneNumber
  • Url

The only input scope values that respond to computers set to display English are: Default, EmailSmtpAddress, Number, Search, TelephoneNumber, and Url.  Here’s what they look like:

EmailSmtpAddress (added “@” and “.com buttons

15-XAML-EmailKeyboard

Url (added “/” and “.com” buttons, smaller space bar, Go key)

15-XAML-URL

Number and TelephoneNumber (shows the default numeric keypad)

15-XAML-Number

Search (same a default keyboard, but Enter key replaced with Search key)

15-XAML-Search

The rest of the InputScope values are generally focused on East Asian languages, and while I mean them no disrespect, I don’t know enough about those character sets to have an intelligent discussion about the subtle differences between FullWidth and HalfWidth characters.

In addition to our InputScope values, it’s important to understand the other options our users can navigate to at any time when the keyboard is on the user’s screen.  Here they are:

Capital Letters

15-XAML-CAPS

Emoji (there’s actually 30 PAGES of emoji, click here to see all of them)

15-XAML-Emoji

Symbols (a second set of symbols after the set shown with the Number keyboard)

15-XAML-Symbols2

Split Keyboard (a user choice, this keyboard is optimized for thumb typing)

15-XAML-SplitKeyboard

Inking Keyboard (this keyboard does handwriting recognition)

15-XAML-InkingKeyboard

Obviously, this is a huge set of input points for us as developers, and by providing the right keyboard for the job will make your app more useful to your users.  There’s also one more keyboard layout, and that’s the one for a PasswordBox control.  A PasswordBox control shows symbols instead of the actual characters that were typed, and the keyboard looks like this:

 15-XAML-PasswordBox

You’ll notice that it also has a “Hide Keypress” button.  There are times when people can see your machine (especially if you’re projecting it to an audience) and you don’t want them to be able to see your keystrokes for your password.  This button doesn’t highlight the buttons when they are tapped.  (You’ll also notice that the Emoji button is disabled, as those characters should not be used for a password.)

In the past, I have written articles about TextBoxes and virtual keyboards, and went on and one about the use cases where you want to pop-up the keyboard without showing the user their input.  A great example of this might be the game HANGMAN.  You want the user to be able to choose a letter, but then you want to dismiss the keyboard so that the user can see their progress.

In Windows 8, this is no longer possible.  You can’t launch the on-screen keyboard via code at all.  In fact, setting the focus on a TextBox control won’t do anything but make the cursor blink.  It specifically requires a tap event (not a mouse click) to occur on the TextBox before the on-screen keyboard will appear.  (This is the same reason why you should use the Simulator when debugging this type of functionality in your apps.)

Summary

Today, we’ve covered off on the variety of keyboards that are available to our users.  We can leverage InputScope values to show the right keyboard at the right time.  In addition, I learned that there are 30 entire pages of Emoji characters to use as well.  (If it’s not obvious, I benefit greatly from writing these articles as well!)

If you would like to see a working application that uses every one of the InputScope values, click the download icon below:

downloadXAML

Tomorrow, we are going to dive into using Context Menus to offer our user contextual commands directly on the app surface.  See you then!

downloadTheTools

Here’s that huge list of Emoji, in case you forgot to click on it:

Emoji

31 Days of Windows 8 | Day #14: Geolocation

HTMLCallout

This article is Day #14 in a series called 31 Days of Windows 8.  Each of the articles in this series will be published for both HTML5/JS and XAML/C#. You can find additional resources, downloads, and source code on our website.

advertisementsample4

Today, we get to talk about one of my favorite features of any development platform: geolocation.  Having knowledge about the user’s location (or more specifically, the device) makes every app better.  Here’s some examples of how:

Line of Business Apps

Know which plant your field manager is visiting today, so that he has all of the appropriate documentation for the machinery in that facility.  In addition, your app could surface the photos and names of the employees in that facility, so that they are more prepared and personable when they arrive.

Games

Identify other nearby players, and make an opportunity to match them up in game.  It will not only potentially improve network latency for them, but you might also form a guild out of nothing.  Create a global game of tag, based solely on proximity, not touching.

Maps

Duh.  We’ll do this as part of the sample code today.

Travel

Recognize the user’s distance and potential travel time from the airport, and alert them to the impending urgency to leave before missing their flight.  In addition, once you’ve established they can’t make it on time, help them find the next available flight without the user having to find it on their own.

Exercise

There are tons of apps available to track your exercise route.  Think running, cycling, etc.  The obvious application of geolocation to these apps is the ability to map the route you took during your travels.  A more important one, however, and I think this responsibility probably falls to the mobile OS manufacturers themselves, is the ability to recognize an accident.  On average, 4500 cyclists a year are victims of hit-and-run situations, where they are left injured (or worse) on the side of the road.  In today’s world, nearly everyone has their phone with them, even when running or cycling.  Imagine that your phone is capable of recognizing a large impact (using accelerometer or gyroscope data), followed by no movement at all.  After 30 seconds of no movement, your phone prompts you to call 911 and send text messages to a pre-selected list of contacts with an SOS message and your location.  After 30 more seconds, it immediately sends that information and dials 911.  This functionality could save lives, as many of these cyclists die needlessly only because nobody knows where they are.  Sorry for being so morbid, but it’s an important thing to think about.

As you can see there is always a way to take location data and make your app even better.  In addition, if you love my ideas above, you are completely welcome to steal them outright.  I will likely never build any of those apps, specifically.  There needs to be 48 hours in every day to make that happen.

Updating our Manifest

Thankfully, getting our geolocation data is pretty easy, and as usual, we have to declare that Location is one of our capabilities in order to use it.  To do this, open the Capabilities section of your package.appxmanifest file, and check the Location box.

14-XAML-Manifest

If you skip this step, and just try implementing the code in the rest of the article, you won’t get any errors, but you also won’t get any data.

Getting our Geolocation Data

In this example, I have constructed an application that constantly tracks the device’s location.  The first thing that got me confused in this process was how to ask the user for permission to start tracking their location in the app.  If you’ll recall, in Day #11 Lock Screen Apps, we had to explicitly prompt the user for permission to access their lock screen.  With Location, however, we don’t.  The simple act of trying to access the data will prompt the user on your behalf.  To make this incredibly easy, here’s ALL of the code you’ll need to access a device’s location from your app.  (Keep in mind that I am sending all of my values to TextBlocks on my MainPage.xaml that display the data.  They are all named like [Datatype]Value to make it obvious.)

Geolocator location;


protected override void OnNavigatedTo(NavigationEventArgs e)

{

    location = new Geolocator();

    location.PositionChanged += location_PositionChanged;

    location.StatusChanged += location_StatusChanged;

}


protected override void OnNavigatingFrom(NavigatingCancelEventArgs e)

{

    location.PositionChanged -= location_PositionChanged;

    location.StatusChanged -= location_StatusChanged;

}


async void location_PositionChanged(Geolocator sender, PositionChangedEventArgs args)

{

    await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>

    {

        Geoposition position = args.Position;


        LatitudeValue.Text = position.Coordinate.Latitude.ToString();

        LongitudeValue.Text = position.Coordinate.Longitude.ToString();

        AccuracyValue.Text = position.Coordinate.Accuracy.ToString();


        TimestampValue.Text = position.Coordinate.Timestamp.ToString();


        if (position.Coordinate.Altitude != null)

            AltitudeValue.Text = position.Coordinate.Altitude.ToString()

                                    + "(+- " + position.Coordinate.AltitudeAccuracy.ToString() + ")";

        if (position.Coordinate.Heading != null)

            HeadingValue.Text = position.Coordinate.Heading.ToString();

        if (position.Coordinate.Speed != null)

            SpeedValue.Text = position.Coordinate.Speed.ToString();

    });

}


async void location_StatusChanged(Geolocator sender, StatusChangedEventArgs args)

{

    await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>

    {

        StatusValue.Text = args.Status.ToString();

    });

}

As you might have guessed, this is an event-driven operation.  When my page loads, I create a new Geolocator object, and add two events: PositionChanged and StatusChanged.

PositionChanged is the important one.  This is where we get all of the useful data like Longitude, Latitude, and Accuracy.  All of these values come from the Geocoordinate class, and as you can see from the code above, there’s several more.

  • Accuracy is the measurement, in meters, of the radius of a circle that has our latitude and longitude value as the centerpoint.  Like this:

14-XAML-Accuracy

  • Timestamp is the actual time that the Location value was read.  This includes timezone information, so you’ll have to convert the times to store everything in UTC.
  • Altitude is the elevation of the device, in meters.  This is likely only to be found in devices with a barometer (we will cover sensors later in this series), but it’s a valuable piece of information if you can get it.
  • AltitudeAccuracy is just like our other Accuracy value, except that it is simple the margin of error for the Altitude value.  It means you are + or – this many meters.
  • Heading will also only be displayed with the appropriate sensor, the compass.  This is measures in degrees relative to true north.
  • Speed can technically be calculated by tracking the lat/long values over time, but they’ve made it incredibly easy for us.  It is measured in meters/second, but is an optional value that the device’s GPS sensor can provide.  This means that not all devices will return a value.

The other code, from the sample above, that I’d like to talk about is the async/await stuff.  You should have noticed that both of our event handler methods have async at the beginning, and then we have something like this:

await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => {};

Because the acquisition of our Location data happens on a background thread, we need to use a Dispatcher to get us back to the primary UI thread in order to write our values to the screen.  Without this code, we will get an error the moment we try to manipulate the UI layer, because background threads do not have access to this directly.  Here’s what my basic UI looks like (no, that is not where I live, but you’d know that if you check out that location):

14-XAML-UI

So we’ve gathered our location data, but there’s still that “StatusChanged” event handler we created earlier.  This is not something we would generally give our user direct access to, as it’s more administrative data for us, but it’s an interesting set of data nonetheless.  It can have six different values:

  • notInitialized is returned when your application has not yet requested permission to access the location data.
  • disabled is the value you will get when the user declines your request to access their location information.
  • notAvailable is returned if the user’s device does not support location data.
  • noData is returned if the user’s device supports location, but can’t acquire any.  This could happen in a scenario where the device is not connected to wi-fi, and is inside a buiding, for example.
  • initializing is the status value you’ll receive between the time the user grants access to location data, and the time you actually start receiving that data.  In future uses of your app, this will also be sent when your app is waiting to access location data for the first time.
  • ready is the golden response, and lets you know that data is available for your use.

So the example I’ve provided you in this article allows you to recognize every time your user’s location data changes, and one that has millions of use cases for.  If you only need this data ONCE, say to tag an image that the user has just taken, you just make a request to the Geolocator object without having to create all of the events I’ve outlined above.  In the method below, we can make one simple call to the GetGeopositionAsync() method instead.

async private void GetLocationDataOnce()

{

    Geoposition position = await location.GetGeopositionAsync().AsTask();


    LatitudeValue.Text = position.Coordinate.Latitude.ToString();

    LongitudeValue.Text = position.Coordinate.Longitude.ToString();

    AccuracyValue.Text = position.Coordinate.Accuracy.ToString();

}


 

In this case, we just need one simple value, one time.  Do not create a loop that makes this call over and over, it’s much slower, and you’ll save tons of machine resources by following the earlier example that registered event handlers.

Using the Simulator to Fake It

If you’re using a traditional desktop PC, you have probably noticed that your machine doesn’t do a great job of determining your location.  Network location can be decent, but it’s unlikely your lat/long coordinates are very accurate.  Enter the simulator.  You can set a very specific location in the simulator without actually having to get on an airplane.  To do this, just open the Location Settings in the simulator:

14-XAML-SimulatorOption

At this point, you can provide latitude, longitude, altitude, and accuracy values:

14-XAML-SimulatorSettings

So there you have it!  You can now write an application that can determine where the user’s device is, and while you’re building it, you can pretend to be anywhere on Earth.  Not a bad way to travel…at least the costs are low. 🙂

Summary

Today, we talked about Geolocation data, and how important it can be to any application in the market.  We looked at tracking a user’s location, as well as getting their location once, for applications that just need the specific location “right now,” but not all the time.

If you would like to download a sample application that includes all of the code from this article, click the icon below:

downloadXAML

Tomorrow, we are going to look at the on-screen keyboard, InputScopes, and TextBoxes.  See you then!

downloadTheTools

31 Days of Windows 8 | Day #13: Navigation

This article is Day #13 in a series called 31 Days of Windows 8.  Each of the articles in this series will be published for both HTML5/JS and XAML/C#. You can find additional resources, downloads, and source code on our website.

advertisementsample4

We have spent the last few days getting pretty technical around updating the system with information to the let user know what’s going on.  In fact, in the first 12 days of this series, we’ve spent very little time talking about how to do one of the most common activities we’ll encounter in Windows 8 development: navigating between XAML pages.

Today, we’ll right that wrong by diving in to this subject.  There are three specific scenarios I want to make sure we cover in this article:

  • The simple act of navigation from Page A to Page B.  What happens when, and what information is available to us?
  • Passing data from one page to another.  This doesn’t just include strings and integers, we can also pass entire objects between pages.
  • Caching pages.  When a user clicks the back button, they don’t want to discover that all of the data they entered has disappeared.  We’ll discuss this more later.

Navigating Between Pages in Windows 8 XAML

It seems that every time we encounter a new platform, there’s also a new way to navigate between pages in a XAML application.  Windows 8 is no different in that regard.  This process is easily explained by walking you through creating some pages, so let’s start there.

Create a new Blank App Template, and then add two new Basic Page items to it.  For this example, you can call them PageA.xaml and PageB.xaml.

13-XAML-BasicPage

In each of those pages, there is a line of XAML that sets the AppName.

<Page.Resources>
    <x:String x:Key="AppName">My Application</x:String>
</Page.Resources>

 

Normally, we would move this to our App.xaml file, and let it apply to all of the pages in our application.  For today, we’re going to use this simple mechanism to give each of our pages a distinct name that we can see when it is loaded.  Set the value of PageA.xaml’s AppName to “Page A” and PageB.xaml’s AppName to “Page B” so that your pages look like this:

13-XAML-PageA 13-XAML-PageB

To make your sample easy to use, we’re also going to make a quick change to our App.xaml.cs file.  Near the bottom of the OnLaunched() method in App.xaml.cs is some code that looks like this:

if (rootFrame.Content == null)
{
    if (!rootFrame.Navigate(typeof(MainPage), args.Arguments))
    {
        throw new Exception("Failed to create initial page");
    }
}

You will want to change the reference from typeof(MainPage) to typeof(PageA).  Like this:

if (rootFrame.Content == null)
{
    if (!rootFrame.Navigate(typeof(PageA), args.Arguments))
    {
        throw new Exception("Failed to create initial page");
    }
}

This will cause your application to start up with the initial page being PageA.xaml.  At this point, go ahead and run your project.  You should see it start with the Splash Screen, and then PageA should load.  You should also notice that even though our preview in Visual Studio 2012 shows an arrow icon next to our page title, it is bound to whether or not the page is capable of “going back” with the Frame.CanGoBack property.  We’ll talk more about that a little later.

For now, let’s get to navigating.  You’ve technically already seen it in our App.xaml.cs file, but it looks a little different when you’re just going from page to page.  I’ve added a <Button> control to my PageA.xaml file, right before the <VisualStateManager> section.  The XAML for that looks like this:

<Button x:Name="PageBButton"
        Grid.Row="1"
        Content="To Page B"
        Width="150"
        Height="150"
        Click="PageBButton_Click" />

 

 

In the event handler for that <Button>, we write our first navigation statement (finally!)

private void PageBButton_Click(object sender, RoutedEventArgs e)
{
    Frame.Navigate(typeof(PageB));
}

 

 

As you can see, it’s a pretty simple process.  So let’s make it a little more complicated now, by adding a navigation button to Page B.  This might seem like a repetitive, simple task, but you’ll find that we can get into trouble rather quickly.  (You should run your project at this point to make sure that you actually navigate to your Page B file.) Add the same type of <Button> and event handler to PageB, but obviously point it at PageA this time.  Now, you have a button on each page that points to the other.  If you only use those buttons to do your navigation, you end up creating a HUGE back navigation stack, and it makes any concept of a Back button completely irrelevant. What we need to do in this case is to implement the GoHome event handler which is part of the LayoutAwarePage object that we’re using.  To effectively illustrate this example, add a second button to your PageB.xaml, with an accompanying new event handler. In this event handler, however, we’re not going to navigate to a page.  Instead, we’re going to create the GoHome event, and call that.  Here’s how that looks:

protected override void GoHome(object sender, RoutedEventArgs e)
{
    if (this.Frame != null)
    {
        while (this.Frame.CanGoBack) this.Frame.GoBack();
    }
}

 

private void HomeButton_Click(object sender, RoutedEventArgs e)
{
    base.GoHome(sender, e);
}

 

As you can see, our GoHome method runs a quick loop attempting to “GoBack” until it can’t anymore.  At that point, we end up back at the top of the navigation stack, on our initial page.  It’s a nice trick, but I think all of this is best illustrated with a quick video:

Passing Data Between XAML Pages in Windows 8

Next, we’re going to want to pass data between our pages.  Maybe an object, maybe a string, but data nonetheless.  As it turns out, our Frame.Navigate() method is overloaded to also accept a data parameter. For this sample, I’ve added a TextBox and a Button to my PageA, but at this point, I’m going to assume you know how to do that.  The important part of this is where I have an event handler that pulls the text value out of the TextBox and sends it as part of the Navigate() method.  Like this:

private void GoButton_Click(object sender, RoutedEventArgs e)
{
    Frame.Navigate(typeof(PageB), TextBoxValue.Text);
}

 

 

On the other side, on PageB, we need to catch this data and display it.  Again, I’ve added a TextBlock in my sample code (which you can download at the end of this article), but the important piece is my new OnNavigatedTo event handler, and catching our data as it arrives.

protected override void OnNavigatedTo(NavigationEventArgs e)
{
    base.OnNavigatedTo(e);

 

    string text = e.Parameter as string;

 

    if (!string.IsNullOrWhiteSpace(text))
    {
        TextBlockValue.Text = text;
    }
    else
    {
        TextBlockValue.Text = "You need to pass a string. Press back and enter a value.";
    }
}

In PageB, we can grab the passed value from NavigationEventArgs.Parameter, where I am casting it as a string value.  You will need to cast your value to the appropriate type before you can use it, but once you have, you’ve tossed data from one page to the next!

In addition, I mentioned earlier that you can send complete objects using this mechanism as well.  Remember our Element class from way back in Day #4?  I’m going to pass a custom Element object from PageA to PageB in the next example.  Here’s PageA’s code:

private void Gallium_Click(object sender, RoutedEventArgs e)
{
    Frame.Navigate(typeof(PageB), new Element { AtomicNumber = 31,
                                                AtomicWeight = 69.72,
                                                Category = "Other Metals",
                                                Name = "Gallium",
                                                Symbol = "Ga",
                                                State = "Solid" });
}

You can clearly see that we’re passing a brand-new Element object to PageB.  Here’s PageB catching that data:

protected override void OnNavigatedTo(NavigationEventArgs e)
{
    base.OnNavigatedTo(e);

 

    Element gallium = e.Parameter as Element;
    TextBlockValue.Text = gallium.Category;
}

 

Caching Pages For Back Button Performance

The last thing we want to look at related to navigation is page caching.  For this final example, I am using our sample application in the state where I was passing string values back and forth.  You may have noticed, if you built your own sample app, that if you type something in the TextBox on PageA, and send that data to PageB, when you click the Back button to return to PageA, it doesn’t remember what you typed in the box.  This is an incredibly frustrating user experience pattern that you see on the web all the time.

We can avoid this with one simple line in the constuctor of the pages we want to cache:

public PageA()
{
    this.InitializeComponent();
    NavigationCacheMode = NavigationCacheMode.Enabled;
}

After you set the NavigationCacheMode, you will find that your TextBox values (and everything else on your page) will be cached in the back stack.  Give it a try…it’s a much better experience, and doesn’t require us to populate and repopulate the form every time the user returns to the page.

Summary

This was an extensive overview of navigation in XAML apps for Windows 8.  We covered moving between pages, passing data between pages, and caching those pages for when the user clicks the back button.

If you would like to download the complete code sample from this article, you can click the icon below.  (Please note that the Gallium button is currently disabled, you’ll need to uncomment the event handler for that button, as well as the code in PageB.xaml.cs to make that work.  PageB can only accept one type of parameter at a time, and it’s currently set up for the string.)

downloadXAML

Tomorrow, we’re going to start our conversation determining a user’s current location using GeoLocation, including the rules that go with using this technology.  See you then!

downloadTheTools

31 Days of Windows 8 | Day #12: Background Tasks

This article is Day #12 in a series called 31 Days of Windows 8.  Each of the articles in this series will be published for both HTML5/JS and XAML/C#. You can find additional resources, downloads, and source code on our website.

advertisementsample

Today, we are talking about Background Tasks.  The short way to describe Background Tasks is this:

A Background Task is the code that runs when your app doesn’t.

Think of the scenarios:

  • Continue streaming audio, even when the user is running another app.
  • Update the user’s Live Tile to reflect new data.
  • Pop a Toast Notification to let the user know something important has happened.
  • Update the user’s lock screen, even when the device is locked.

Getting a Background Task established and registered with the system is a two-step process.  First, you have to register the Background Task in your package.appxmanifest file.  Once that has been done, you still need to register the events of that Task with the system from your application code, and then there are additional events to manage what happens when Background Tasks finish.  We will cover these scenarios in this article.

Creating a Background Task Class

My first step is always to create a secondary project that will contain my Background Tasks.  This isn’t required, but it’s a nice visual separation of your code.

12-XAML-AddProject

When you create a new Project, choose “Windows Runtime Component” as the project type.

12-XAML-WindowsRuntimeComponent   By default, you are given a class named Class1.cs.  You can either rename it, or just delete it and add a new Class to the new project.  In either case, you’re going to create a Class file named TileUpdater.cs.

Now, Background Tasks must implement a very specific interface: IBackgroundTask.  It only implements one method, Run(), and this is the method that will be called when our app kicks off the Background Task.  Just to get you started, here’s what my C# looks like after implementing the interface:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.ApplicationModel.Background;

namespace BackgroundTasks
{
    public sealed class TileUpdater : IBackgroundTask
    {
        public void Run(IBackgroundTaskInstance taskInstance)
        {
            //We will add code here later.
        }
    }
}

 

I’ve added a comment where our code will reside, but for now, this is a good start.

Setting Up Your Package.Appxmanifest File

The next step in this process is to declare that we will be using Background Tasks in this application.  We do this in the package.appxmanifest file, in the Declarations section, as illustrated by the screenshot below (click to enlarge):

12-XAML-Appxmanifest

As you can see, we’ve added a declaration for Background Tasks (you will a new one of these for each Background Task you want to add to your project), and set the entry point to be BackgroundTasks.TileUpdater, our new class file.  Next, we need to register this task in our actual application, so that Windows 8 knows to run it at the appropriate times.

Registering Your Background Task

We’re going to take a couple of steps in this code of our MainPage.xaml.cs file, starting with checking to see if our Background Task has already been registered to the system.  I generally do this as soon as the page loads, in my OnNavigatedTo method.  I’ve create a new CheckTaskRegistration() method that checks this status for me, and sets a global Boolean value in the page.  You could certainly do this in your App.xaml.cs file as well, but for our simple purposes, this location works fine.

bool isTaskRegistered = false;

protected override void OnNavigatedTo(NavigationEventArgs e)
{
    CheckTaskRegistration();
}

private void CheckTaskRegistration()
{
    foreach (var task in BackgroundTaskRegistration.AllTasks)
    {
        if (task.Value.Name == "TileUpdater")
        {
            isTaskRegistered = true;
            break;
        }
    }

    if (!isTaskRegistered)
    {
        RegisterBackgroundTask("TileUpdater", "BackgroundTasks.TileUpdater");
    }
}

As you can see, we are looping through the BackgroundTaskRegistration.AllTasks collection, because we could have multiple Background Tasks running under our application, and in this case, I’m only interested in the one: TileUpdater.  You can also see that I’ve made a call to RegisterBackgroundTask() if the task is not currently registered.

It is up to you how you handle this case, but in my application, I want to make sure that my Background Task is always registered, and if it has been unregistered for some reason, I want to add it back in.  Here’s what my RegisterBackgroundTask() method looks like:

private void RegisterBackgroundTask(string name, string entrypoint)
{
    BackgroundTaskBuilder btb = new BackgroundTaskBuilder();
    btb.Name = name;
    btb.TaskEntryPoint = entrypoint;
    btb.SetTrigger(new SystemTrigger(SystemTriggerType.InternetAvailable, false));

    BackgroundTaskRegistration task = btb.Register();
}

You can see that I’m passing in the name and entrypoint values, but you could certainly hard code those depending on your situation.  Since this application could have multiple Background Tasks, I decided to make this construction a little simpler and pass in some parameters.

In our registration method, we create a BackgroundTaskBuilder object, set the name and entry point, and then determine a SystemTrigger that will kick our Background Task off.  In this case, I’ve chosen the easily testable InternetAvailable trigger.  To try it, we’ll be cutting off our internet access on our machine.

If you ever have a need to unregister your Background Task, it’s pretty simple.  Here’s a sample method, UnregisterBackgroundTask() that you can use to remove the Task.

private void UnregisterBackgroundTask(string name)
{
    foreach (var task in BackgroundTaskRegistration.AllTasks)
    {
        if (task.Value.Name == name)
        {
            task.Value.Unregister(true);
        }
    }
}

In this example, we loop through the Tasks that are registered again, and if we find the one with the name we’re looking for, we call its Unregister() method, confirming with the true parameter.

So we’ve worked through registering and unregistering our Background Task, and we now have specified that our application should kick off our Background Task when the time zone of the machine changes.  Let’s write some actual code in our Background Task class, and then give this thing a test.

Making Your Background Task DO Something

Earlier, we created a file named TileUpdater.cs in our new Windows Runtime Component project, and we left some space to add some code to the Run() method that must be implemented as part of the IBackgroundTask interface.  Here’s what that same file looks like with code to update our Live Tile:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.ApplicationModel.Background;
using Windows.Data.Xml.Dom;
using Windows.UI.Notifications;

namespace BackgroundTasks
{
    public sealed class TileUpdater : IBackgroundTask
    {
        public void Run(IBackgroundTaskInstance taskInstance)
        {
            XmlDocument tileData = TileUpdateManager.GetTemplateContent(TileTemplateType.TileSquareText04);
            XmlNodeList textData = tileData.GetElementsByTagName("text");
            textData[0].InnerText = "Background updates are absolutely amazing. #31daysofwin8";
            TileNotification notification = new TileNotification(tileData);
            notification.ExpirationTime = DateTimeOffset.UtcNow.AddSeconds(30);
            TileUpdateManager.CreateTileUpdaterForApplication().Update(notification);
        }
    }
}

Obviously, we could write a similar Background Task to implement sending a Toast notification, updating the Lock Screen, or other valuable calls to web services for example.

Summary

There’s one more thing to note about Background Tasks: they’re much harder to debug than the code in your actual application.  In fact, Microsoft has written an entire article about exactly how to Debug Your Background Tasks.  I highly recommend reading it.  They have also created a quickstart tutorial called Create and Register a Background Task.

If you would like to download the working sample code from this article, click the icon below:

downloadXAML

Tomorrow, we’re going to shift gears again, and start talking about Navigation.  Specifically, how to navigate between pages in a XAML application, and pass parameters and data as part of that process.  See you then!

downloadTheTools

31 Days of Windows 8 | Day #11: Lock Screen Apps

This article is Day #11 in a series called 31 Days of Windows 8.  Each of the articles in this series will be published for both HTML5/JS and XAML/C#. You can find additional resources, downloads, and source code on our website.

advertisementsample

Today we cover the last bit of notifications in Windows 8: the Lock Screen.  If you’re running Windows 8 on your machine, you’ve likely gotten pretty familiar with the lock screen.  It shows you how many emails you’ve received, Facebook messages, the clock, and your connectivity status.  Here’s my current lock screen:

11-XAML-LockScreen

Yes, that’s a photo of my screen.  I spent 30 minutes this morning hunting for a solution to take a screenshot of my lock screen, and was unsuccessful.  (Yes, I know I could fire up a VM, or remote into my machine, but I don’t have any of that stuff set up right now.)  Anyways, you can also see that I’m only writing this article a few days ahead of publication time, and I have a meeting in 30 minutes.

We, as developers, have the ability to add our badges to this lock screen as well, but it’s dangerous to go alone.  Take this.  It’s Microsoft’s guidance on the best ways to utilize the Lock Screen notification area.

Configuring our Manifest

First, we need to set our package.appxmanifest file to allow Lock screen notifications:

11-XAML-ApplicationUITab

When you do this, you’ll notice the screen lights up with red X symbols.  When lock screen notifications are enabled, we are required to have a Badge Logo, and since we chose the option that includes tile updates as well, we’re required to provide a Wide Logo image as well.  Here’s my Application UI tab with those files added:

11-XAML-ApplicationUITab2

You’ll notice we now have a new red X, which lets us know that “If lock screen notifications are enabled, you must specify one or more Background task declarations of type ‘Timer’, ‘Control channel’, or ‘Push notification.’”

What this means is that Lock Screen apps generally expect to be updated from a Background Agent.  Let’s flip over to our Declarations tab, and add Background Tasks, like this:

11-XAML-Declarations

In my example app, we’re not actually going to create a background task, however.  I’m going to cover that extensively tomorrow.  Instead, we’re going to focus specifically on the processes and code that allows us to update our Lock Screen information.

Asking for Permission

Before you can ever start thinking about writing content to the user’s lock screen, you need to ask for their permission.  Now, you don’t HAVE to ask, but without asking their permission, the road to the Lock Screen is perilous and fraught with danger.  Here’s what I mean:

You get ONE, and only ONE opportunity to ask the user for permission to be on their lock screen.  If you ask once, and they say “Don’t Allow”, you’re not even capable of asking again.  Here’s what it looks like when you ask:

11-XAML-BackgroundRequest

And here’s how you do it:

BackgroundAccessStatus status = await BackgroundExecutionManager.RequestAccessAsync();

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

 

If you never ask, the only way to get on the lock screen is for the user to open their PC Settings, and explicitly add you, like this (nevermind that scary picture of my unshaven face…unless you want to support my Movember campaign):

11-XAML-LockScreenSettings

Users can select up to 7 apps to be displayed on their Lock Screen.  We want to make sure we’re one of them.  So, because our status can change at the user’s whim, we should be responsible before trying to send updates to their Lock Screen.

Making Sure You Have Permission

This is not a required step.  You can have your app, or your background task (as we will cover tomorrow) continue sending updates even if you don’t have permission.  That being said, your updates also won’t ever be seen by the user.  Without permission, your updates will disappear into the ether.

Here’s how we check to see if the user has granted us permission to update the lock screen:

BackgroundAccessStatus status = BackgroundExecutionManager.GetAccessStatus();
            
if ((status == BackgroundAccessStatus.AllowedWithAlwaysOnRealTimeConnectivity) ||
    (status == BackgroundAccessStatus.AllowedMayUseActiveRealTimeConnectivity))
{
   //SEND YOUR UPDATE HERE.
}

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

 

So at this point, we’ve covered asking the user for permission, and then checking to make sure that permission has been granted.  The next step is actually sending the update.

Updating the Lock Screen

Sending an actual update will look pretty familiar if you’ve read the previous two articles.  (Day #9 – Live Tiles, Day #10 – Toast Notifications)  Like those previous examples, we are grabbing a template that consists of XML (in this case, it’s incredibly simple):

<badge value="badge_value"/>

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

 

Next, we need to specify the value that we want to display.  We have several options in this scenario.  Not only can we use any number from 1 – 99, but we also have a number of glyphs to choose from.  The best part is that the template is smart enough to recognize the difference, so the only thing that will change in our code is the actual value we pass in.  Here’s the code to make the update to the badge:

XmlDocument badgeData = BadgeUpdateManager.GetTemplateContent(BadgeTemplateType.BadgeNumber);
XmlNodeList badgeXML = badgeData.GetElementsByTagName("badge");
((XmlElement)badgeXML[0]).SetAttribute("value", "31");
 
BadgeNotification badge = new BadgeNotification(badgeData);
BadgeUpdateManager.CreateBadgeUpdaterForApplication().Update(badge);
 

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

 

You can see that in my SetAttribute() method call, I pass a value of 31.  That results in a Lock Screen badge that looks like this:

WP_20121106_004

If you would rather use one of the glyphs, here’s a list of what’s available, courtesy of the Badge overview page on MSDN.

11-XAML-GlyphList

To specify a glyph, we only need to change the value in our SetAttribute() method, like this:

((XmlElement)badgeXML[0]).SetAttribute("value", "Playing");

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

 

That’s about it for Lock Screen apps…I hope you learned something today.  Wait…there’s one more thing.  I forgot to mention that when we chose “Badge and Tile Text” in our appxmanifest file, we enabled these Badges we’re creating to appear on our Tile as well.  (This is why the WideTile.png file was required.)  Here’s what my Live Tile looks like with that same “Playing” badge applied:

11-XAML-WideLogo

Summary

We can update our Lock Screen information from our app at any time, but the tricky part is getting the user’s permission.  Once you’ve gotten that, updating the information is pretty simple, as we saw in this article.

If you would like to download a working application that uses the code from this article, click the icon below:

downloadXAML

Tomorrow, we’re going to wrap up the last three days by talking about Background tasks.  We’ll show how to update Live Tiles, Toast notifications, and Lock Screen data from a background task.  See you then!

downloadTheTools