Visually Located

XAML and GIS

Fixing the AppBarButtonStyle for ToggleButton support in your Win8 apps

With the RTM release of Visual Studio 2012 the Visual Studio team made some improvements to the various AppBar button styles. One of these awesome improvements was to add support for ToggleButtons. Now you can use any of these out-of-the-box styles with Buttons AND ToggleButtons. This is pretty awesome… Except for the fact that the style is missing a required TextBlock. This TextBlock toggles the color of the button. Without it you do not get a visual indication that the ToggleButton is checked. Even worse, is that the application crashes when the ToggleButton is checked.

To fix this, open the StandardStyles.xaml file and go to the AppBarButtonStyle. Insert the following line directly under the “BackgroundGlyph” TextBlock

<TextBlock x:Name="BackgroundCheckedGlyph" Visibility="Collapsed" Text="&#xE0A8;" FontFamily="Segoe UI Symbol" FontSize="53.333" Margin="-4,-19,0,0" Foreground="{StaticResource AppBarItemForegroundThemeBrush}"/>

After inserting that line, the Grid within the StackPanel should look like:

<Grid Width="40" Height="40" Margin="0,0,0,5" HorizontalAlignment="Center">
    <TextBlock x:Name="BackgroundGlyph" Text="&#xE0A8;" FontFamily="Segoe UI Symbol" FontSize="53.333" Margin="-4,-19,0,0" Foreground="{StaticResource AppBarItemBackgroundThemeBrush}"/>
    <TextBlock x:Name="BackgroundCheckedGlyph" Visibility="Collapsed" Text="&#xE0A8;" FontFamily="Segoe UI Symbol" FontSize="53.333" Margin="-4,-19,0,0" Foreground="{StaticResource AppBarItemForegroundThemeBrush}"/>
    <TextBlock x:Name="OutlineGlyph" Text="&#xE0A7;" FontFamily="Segoe UI Symbol" FontSize="53.333" Margin="-4,-19,0,0"/>
    <ContentPresenter x:Name="Content" HorizontalAlignment="Center" Margin="-1,-1,0,0" VerticalAlignment="Center"/>
</Grid>

Now your app will not crash with that ToggleButton!

Next, read Part 2 to fix the VisualState of the ToggleButton.

Adding multiple lines of text to your Win8 tile update

Live tiles is one of the best things about Windows Phone and WinRT. I love how easy it is to add updates to your tiles in Windows Phone but hate how limited the updates are allowed to be. With WinRT comes a new API and more robust tile updates. There are many different types of tile updates and your app should support AT LEAST one square and one wide tile. If you’re like me (and I know I am), I started with the C# WinRT sample for App tiles and badges. I began looking at the code and could easily see that you use the TileUpdateManager to update your tile. The TileUpdateManager needs a TileNotification in order to update your tile. Here is where I quickly became lost in this rather complex sample. The TileNotification needs to be created with XML (an XmlDocumentto be exact) but I had not idea what XML elements are needed (Seriously, is all of the abstraction really needed here? This is suppose to be a simple sample to let devs see how to quickly and easily create a tile update). All I wanted to know was how to format the XML!

I was about to give up on the sample and look online (which so far hasn’t netted much for WinRT searches) when I decided to run the app. I was very pleased to find that the app will output what the XML would look like for the type of tile update you select.

image

This was perfect! Exactly what I was looking for. I copied the XML provided and put it into my app and I now had a tile update. I was now very happy with this sample after becoming very frustrated with it. As easy as this was I figured adding one more line of text must be just as easy. So I added a new <text> element to each wide and square tile.

<tile>
  <visual version="1">
    <binding template="TileWideText03">
      <text id="1">Hello World!</text>
      <text id="2">My very own tile notification</text>
    </binding>
    <binding template="TileSquareText04">
      <text id="1">Hello World!</text>
      <text id="2">My very own tile notification</text>
    </binding>
  </visual>
</tile>

After adding the two new lines, I ran the app, switched to the start screen and found that there was only one line of text. This was true for both the wide and square tile.

I’m pretty new to updating tiles in WinRT so I’m sure it’s something that I did. Time spans about a half hour later trying many changes to the XML and it turns out that the problem was with the version attribute of the visual element. I removed the version attribute and everything worked great!

<tile>
  <visual>
    <binding template="TileWideText03">
      <text id="1">Hello World!</text>
      <text id="2">My very own tile notification</text>
    </binding>
    <binding template="TileSquareText04">
      <text id="1">Hello World!</text>
      <text id="2">My very own tile notification</text>
    </binding>
  </visual>
</tile>

So, if you are starting with the sample as I did, do not use the version attribute of the visual element. I’m hoping that this is fixed with the RTM version of Windows 8. Only a few hours left until I can test for myself…

Easily share status with your WinRT App (AKA Share Source Charm)

There are two types of way to share use the Share Charm win Windows8. Your app can be a Share Source, or a Share Target. Think of Share Target as your email or Twitter/Facebook apps. Share Source is everything else. I was  trying to add in the ability to share status within an app and thought it would be a pretty easy thing to do. It was easy, but took me awhile searching the web to find out how to do it.  I’m hoping to make that a little easier for you.

The first thing is to tell the app that users have the ability to share from your app. I thought this was going to be hidden in the app manifest file but was surprised to discover that this is done in code. To register your app as one that can share information, you must subscribe to the DataRequested event from the DataTransferManager.

var dataTransferManager = DataTransferManager.GetForCurrentView();
dataTransferManager.DataRequested += DataTransferManagerOnDataRequested; 

I found one example online that said to put that into the constructor of your “MainPage” or first page of the app. The problem with this is that the constructor for pages gets called when navigating backward as well as when going forward. When you navigate backward, the constructor will be called and will register for the event again you get an InvalidOperationException that says “A method was called at an unexpected time.” I’m guessing you get this error because you have already registered for the event with the DataTransferManager and cannot do it again. This is just a wild guess. Instead of wrapping this call with a try/catch in the constructor of your page, you can register for the event within your app.xaml.cs file. You’ll want to do this when the root frame is loaded.

protected override void OnLaunched(LaunchActivatedEventArgs args)
{
    ...
 
    var rootFrame = new Frame();
    rootFrame.Loaded += OnRootFrameLoaded;
    
    ...
}
 
private void OnRootFrameLoaded(object sender, RoutedEventArgs routedEventArgs)
{
    var dataTransferManager = DataTransferManager.GetForCurrentView();
    dataTransferManager.DataRequested += DataTransferManagerOnDataRequested; 
}

The advantage of registering for the event within the page is that you can specify which pages in your app can share. If you don’t want your second page to share, you can unsubscribe from the DataRequested event when the user navigates away from the page.

Next you need to decide what to share from your app. This is done from your DataRequested event handler. This seems to be the most cryptic part of sharing. There are so many options to set, but there is not much out there to help you know which ones to set.

You specify your sharing with the DataPackage object. the DataPackage has a few ‘SetXXX’ methods for settings various properties and a Properties property of type DataPackagePropertySet. In order for your app to share, you must set the Title of the DataPackagePropertySet and at least one of the ‘SetXXX’ methods. If you do not, you’ll see the following message when trying to share “There was a problem with the data from <Your App>.”

private void DataTransferManagerOnDataRequested(DataTransferManager sender, DataRequestedEventArgs args)
{
    DataPackage package = args.Request.Data;
    package.Properties.Title = "Share Text Example";
    package.SetText("This is what I'm sharing");
}

Each Share Target app is different and expects different properties/methods to be set. I tested with MetroTwit, Rowi, and Tweetro as well as the standard Windows8 apps. I was able to share with MetroTwit, Rowi and the Mail app by only using the SetText method. The mail app would take the Title and use that as the subject. Both MetroTwit and Rowi used the text within the SetText method as the tweet. Tweetro seems to be lacking with sharing. I had to use the SetUri method to enable sharing with it, and it still would not set the tweet text. Using the SetUri method also enabled sharing with the People app. Rowi seemed to be the best Twitter target app. It would use both the Text (SetText) and Uri (SetUri) in the tweet.

Play around with the different ‘SetXXX’ methods to see what other apps allow you to share. One thing I found through testing was that the Description of the DataPackagePropertySet is only used as a nice summary for the user.