Quickstart: Pinning a secondary tile (XAML)

Note  Not using C#/VB/C++? See Quickstart: Pinning a secondary tile (HTML).

 

This topic walks you through the steps to create a secondary tile for an app and pin it to the Start screen.

Prerequisites

To understand this topic, you will need:

  • A working knowledge of secondary tile terms and concepts. For more information, see the Secondary tiles overview.
  • The ability to create a basic Windows Store app with C# or C++ using Windows Runtime APIs. For more information, see Create your first Windows Store app using C# or Visual Basic.
  • An understanding of how to use Microsoft Visual Basic to create code-behind for an Extensible Application Markup Language (XAML)-based Windows Store app.

Important  To see the code supplied in this topic used in a full sample, see the Secondary tiles sample. The sample is provided in JavaScript, C#, C++, and Visual Basic versions.

 

Instructions

1. Optional: Add namespaces

To simplify your code, add the following lines to the .cs file(s) in your project that contain the code (or your version of it) found in the rest of this quickstart. All of the code in this topic assumes that you've added these lines and will not compile as-is otherwise. Windows.UI.StartScreen contains the secondary tile objects and Windows.UI.Xaml.Controls is used with app bars and buttons.

using Windows.UI.StartScreen;
using Windows.UI.Xaml.Controls;

2. Add an app bar with a pin/unpin button

On Windows, you normally present a pinning opportunity to the user through a Pin to Start button in your app bar. For information on how to create an app bar, see Quickstart: Adding app bars.

Note  For Windows Phone Store apps, pinning is usually done through a context menu rather than a button on an app bar.

On Windows when the user selects your pin/unpin button, a flyout appears to ask the user for confirmation. To keep the app bar from being dismissed while the flyout is showing, set the IsSticky property to True.

This code is added to the .xaml page in your project for which the rest of code in this topic is the code-behind.

<Page.BottomAppBar>
    <CommandBar x:Name="SecondaryTileCommandBar" Padding="10,0,10,0" IsSticky="True" IsOpen="True">
        <AppBarButton x:Name="PinUnPinCommandButton" Icon="Pin" Label="Pin" />
    </CommandBar>
</Page.BottomAppBar>

3. Provide a unique ID for your secondary tile

public const string appbarTileId = "MySecondaryTile";

4. Create a function to set the button as pin or unpin

Your pin button's action toggles between pinning and unpinning the secondary tile. In this example, we create a function to set the button appropriately, using system-provided icons for a consistent appearance with other apps. This function is called as part of your app's initialization code, whenever the app bar is opened, and immediately after a successful pin/unpin operation.

private void ToggleAppBarButton(bool showPinButton)
{
    if (showPinButton)
    {
        this.PinUnPinCommandButton.Label = "Pin to Start";
        this.PinUnPinCommandButton.Icon = new SymbolIcon(Symbol.Pin);
    }
    else
    {
        this.PinUnPinCommandButton.Label = "Unpin from Start";
        this.PinUnPinCommandButton.Icon = new SymbolIcon(Symbol.UnPin);
    }

    this.PinUnPinCommandButton.UpdateLayout();
}

5. Show the appropriate button and assign a button click handler

In this example, as part of the app's initialization, we use the ToggleAppBarButton function from the last step to check whether the secondary tile is already pinned and set the button text accordingly.

We then assign the handler pinToAppBar_Click to the pin button's click event. We'll show you how to implement the event handler in the next step.

Call the code shown in this step, together with any other initialization you need to perform, as part of your app's initialization every time that app is launched.

void Init()
{
    ToggleAppBarButton(!SecondaryTile.Exists(MainPage.appbarTileId));
    this.PinUnPinCommandButton.Click += this.pinToAppBar_Click;
}

6. Create and pin the secondary tile in the button's event handler

This example implements a single function that can be called by the pin button's click event handler. This function collects several steps that lead to the pin request:

  • Assigns property values that are required for secondary tile creation
  • Creates the secondary tile object
  • Specifies additional properties of the secondary tile
  • Gets the screen coordinates used to display the confirmation flyout (Windows only)

Some of the properties of the secondary tile must be set before it can be pinned. If you attempt to pin a secondary tile without one or more of these properties, the attempt will fail. These are the required properties:

  • A unique ID for the tile
  • Short name (Windows 8.0 only)
  • Display name
  • An argument string that is passed to the parent application when the secondary tile is activated
  • A logo image
  • Tile options (Windows 8.0 only)

As an example argument string, this sample passes the time the secondary tile was pinned to the Start screen.

Note  On Windows Phone 8.1, the display name is never shown on a medium (150x150) secondary tile. Also, all phone tiles initially pin as medium tiles, so the newTileDesiredSize parameter is ignored on the phone.

Note  If you provide the same ID as that of an existing secondary tile, the existing secondary tile will be overwritten.

 

string displayName = "Secondary tile pinned through app bar";
string tileActivationArguments = MainPage.appbarTileId + " was pinned at=" + DateTime.Now.ToLocalTime().ToString();
Uri square150x150Logo = new Windows.Foundation.Uri("ms-appx:///Assets/square150x150Tile-sdk.png");
TileSize newTileDesiredSize = TileSize.Square150x150;

Next, we create the secondary tile object. This version of the constructor creates a medium tile. Note that if your secondary tile receives notifications, it is a best practice to declare all tile sizes. This is done by providing logo images through the SecondaryTileVisualElements class.

SecondaryTile secondaryTile = new SecondaryTile(MainPage.appbarTileId, 
                                                displayName, 
                                                tileActivationArguments,
                                                square150x150Logo, 
                                                TileSize.Square150x150);

Now that you have a secondary tile object, you can specify secondary tile properties that are not set through the constructor. This example specifies the foreground text color and small logo and specifies that the display name is shown on the tile.

Note  On Windows Phone 8.1, neither the small logo nor the display name are shown on a medium (150x150) secondary tile and the foreground text color cannot be specified, so those properties as set in this example are ignored on the phone.

secondaryTile.VisualElements.ShowNameOnSquare150x150Logo = true;                       
secondaryTile.VisualElements.ForegroundText = ForegroundText.Dark;                        
secondaryTile.VisualElements.Square30x30Logo = new Uri("ms-appx:///images/square30x30Tile-sdk.png");

On Windows, the user must confirm before a secondary tile is pinned. In the confirmation dialog, the user can override the tile's display name and select from various tile sizes to pin. The confirmation flyout should be shown near the button that invoked the pin request. This example retrieves the bounding rectangle of the pin button ("sender") and specifies that the confirmation dialog should display above the button.

Note  On Windows Phone 8.1, the user is not presented with a confirmation dialog; the tile is simply pinned to the Start screen as a medium tile and without a display name. The code shown here would be ignored.

Windows.Foundation.Rect rect = MainPage.GetElementRect((FrameworkElement)sender);
Windows.UI.Popups.Placement placement = Windows.UI.Popups.Placement.Above;

Next, the function requests that the secondary tile be pinned.

  • On Windows Phone 8.1, this call pins the tile, suspends the app, and takes the user to the Start screen.
  • On Windows, this call displays the confirmation flyout that asks the user for permission to pin the tile. Using the bounding rectangle of the pin button, this example displays the confirmation flyout above those coordinates. On user approval, Windows creates the secondary tile and places it on the Start screen. The user remains in the app.
bool isPinned = await secondaryTile.RequestCreateForSelectionAsync(rect, placement);

Note  On Windows Phone 8.1, a call to RequestCreateAsync or RequestCreateForSelectionAsync exits the app and takes the user to the Start screen. Because of this, any code that follows the RequestCreateAsync or RequestCreateForSelectionAsync call will not be executed. Therefore, in Windows Phone 8.1 projects, you should listen for the Suspending event so that you can perform anything, such as saving the app state, that needs to be done before the app exits.

When the secondary tile is already pinned, the pin button becomes an unpin button and the button's click event handler unpins the tile. This example provides the code that the handler will asynchronously call to unpin the tile. Again, this call produces a confirmation dialog instead of actually unpinning the tile from the Start screen. On approval, Windows removes the secondary tile from the Start screen.

Note  Any secondary tile can also be unpinned through the Start screen app bar. You have the option of relying on that method for unpinning, in which case you don't need to implement unpin functionality or provide an unpin button.

 

SecondaryTile secondaryTile = new SecondaryTile(MainPage.appbarTileId);
bool isUnpinned = await secondaryTile.RequestDeleteForSelectionAsync(rect, placement);

Finally, we revert the app bar's IsSticky property to false so that the flyout can be dismissed.

rootPage.BottomAppBar.IsSticky = false;

The full pinToAppBar_Click event handler is shown here. Note that the handler calls ToggleAppBarButton after both pinning and unpinning operations. If the operation fails, the button does not toggle.

async void pinToAppBar_Click(object sender, RoutedEventArgs e)
{
#if WINDOWS_APP
    this.SecondaryTileCommandBar.IsSticky = true;
#endif
    
    if (SecondaryTile.Exists(MainPage.appbarTileId))
    {
        // Unpin
        SecondaryTile secondaryTile = new SecondaryTile(MainPage.appbarTileId);
    
        Windows.Foundation.Rect rect = MainPage.GetElementRect((FrameworkElement)sender);
        Windows.UI.Popups.Placement placement = Windows.UI.Popups.Placement.Above;
        
        bool isUnpinned = await secondaryTile.RequestDeleteForSelectionAsync(rect, placement);
    
        ToggleAppBarButton(isUnpinned);
    }
    else
    {
        // Pin
        Uri square150x150Logo = new Uri("ms-appx:///Assets/square150x150Tile-sdk.png");
        string tileActivationArguments = MainPage.appbarTileId + " was pinned at = " + DateTime.Now.ToLocalTime().ToString();
        string displayName = "Secondary tile pinned through app bar";
    
        TileSize newTileDesiredSize = TileSize.Square150x150;
    
        SecondaryTile secondaryTile = new SecondaryTile(MainPage.appbarTileId,
                                                        displayName, 
                                                        tileActivationArguments,
                                                        square150x150Logo,
                                                        newTileDesiredSize);
    
        Uri square30x30Logo = new Uri("ms-appx:///images/square30x30Tile-sdk.png");
        secondaryTile.VisualElements.Square30x30Logo = new Uri("ms-appx:///images/square30x30Tile-sdk.png");
        secondaryTile.VisualElements.ShowNameOnSquare150x150Logo = true;
        secondaryTile.VisualElements.ForegroundText = ForegroundText.Dark;
    
        Windows.Foundation.Rect rect = MainPage.GetElementRect((FrameworkElement)sender);
        Windows.UI.Popups.Placement placement = Windows.UI.Popups.Placement.Above;

#if WINDOWS_APP
        bool isPinned = await secondaryTile.RequestCreateForSelectionAsync(rect, placement);

        ToggleAppBarButton(!isPinned);
#endif

#if WINDOWS_PHONE_APP
       await secondaryTile.RequestCreateAsync();
#endif
    }

#if WINDOWS_APP
    this.BottomAppBar.IsSticky = false;
#endif
}

Summary and next steps

In this Quickstart, you defined a button on an app bar with which a user could pin or unpin a secondary tile. You created the secondary tile, defined many of its properties, and presented the confirmation dialog to the user which results in the final addition of the secondary tile to the Start screen.

After a secondary tile is pinned, the parent app tile then creates a channel Uniform Resource Identifier (URI) so that it can communicate with the secondary tile. For more information, see Quickstart: Sending a notification to a secondary tile.

Secondary Tiles sample

Secondary tiles overview

Quickstart: Sending notifications to a secondary tile

Guidelines and checklist for secondary tiles

SecondaryTile class