Musings of a PC

Thoughts about Windows, TV and technology in general

Category Archives: Windows 8 Development

Migrating a WP Silverlight app to WP XAML – supporting settings

Earlier this year, Microsoft announced Universal Apps – an enhancement in VS2013 that took advantage of improved API compatibility between Windows 8.1 and Windows Phone 8.1 to allow a much greater amount of code sharing between an app for both platforms.

This article is not going to look at that side of things in any detail. Instead, whilst working on a Universal App version of Relative History, it occurred to me that there might be … challlenges … when it comes to dealing with how a user has been using an existing Windows Phone app. The primary reason why there could be challenges is because a Windows Phone Universal App doesn’t use the Silverlight infrastructure so access to things like application settings get handled in a different way.

Upgrading a published Windows Phone app

There is some guidance published by Microsoft on how to upgrade an app. It mostly focusses on upgrading to Silverlight 8.1, which is not of much help to me, but there is some key information about the upgrade process, namely:

  • If testing, it is necessary to copy the ProductID and PublisherID attributes from the published app into the PhoneProductID and PhonePublisherID attributes in the Package.appxmanifest file. This is for the scenario where the earlier version of the app is already deployed onto a device or emulator but not installed from the Store. It is not possible to upgrade an app installed form the Store by deploying a new version of the app from your development computer.
  • If publishing, you simply submit the app to the Store. Microsoft takes care of replacing the product ID and publisher ID with the values from the app you are updating.

I’ll go into some of the above in more detail in a moment, but the key point here is that you cannot upgrade a Store-installed app in testing. If you want to test the process through the Store, here are the steps (thanks to Romasz for his answer on StackOverflow):

  • Publish a Beta version of the existing app – WP7.0/7.1/8.0 Silverlight.
  • Install that from the Store onto your phone.
  • Submit an update to the Beta version in the Store. Add a new package. Do not replace the old package.
  • Your phone will eventually spot the new version and update it. When you run the updated app, it should then execute any code you’ve written to deal with the upgrade process.

Can settings and files be “upgraded”?

My first thought was: when a user upgrades from a Silverlight-based WP app to a XAML-based WP app, what happens to the settings and what happens to any locally-stored files? Let’s see what the community says …:

I got some great responses to that question:

So, the answer is a qualified yes … so the next question is how do we go about it?

Upgrading an app

If you haven’t already done so, you need to install Windows Phone Power Tools (WPPT). This will help because it allows you to browse and access the contents of the app’s private storage. This is useful, for example, if you want to see what you need to be accessing, updating or (in my case) deleting when you migrate from Silverlight to XAML.

As was touched upon earlier and, as Ginny pointed out, you need to make sure that the App ID remains the same. This is the ID string that the operating system uses to identify your app and can be found in WMAppManifest.xml.

Capture

Copy that string into the clipboard then open the file Package.appxmanifest in VS2013 using the XML(Text) Editor. You need to paste the ID you’ve just copied into the PhoneProductId string in that file and save it.

Capture

The PublisherID can be found towards the end of the same XML section in WMAppManifest.xml and this then gets copied into the PhonePublisherId section of Package.appxmanifest.

Now build your app. If it was building successfully previously, it should still build successfully. You can even deploy it to a device or emulator if you want to double-check :-).

Next step is to install the WP Silverlight version of your app to a device or emulator. Use WPPT to install the XAP file. Once installed, run the app and do whatever you need to do in order to get it set up, or get some data installed … whatever is necessary to properly test the upgrade process.

Updating the settings

Once you’ve installed the Silverlight version and used it a bit, you can use WPPT to look at the Isolated Storage for your app:

Capture

Notice how I’ve expanded the Local directory. The main file we’re interested in now is __ApplicationSettings. Everything else will continue to exist after the app is updated by the WP XAML version of the app, and it then becomes up to you whether or not your new version can use those files, update them or delete them. In the case of my app, for example, the Silverlight version of the app uses the local SQL implementation and the data is stored in .sdf files. With the XAML version, I’ve moved to using SQLite so the .sdf files are essentially useless to me. My app will need to delete them in order to free up the storage space, but I’ll also use the contents of __ApplicationSettings in order to ascertain more information about those databases so that I can re-import the data, this time into a SQLite file.

So … onto __ApplicationSettings. If you use WPPT to get the file onto your computer, you can open it in WordPad and see something like this:

Capture

It is important to note that the application settings stored by a WP Silverlight app cannot be accessed through ApplicationData.LocalSettings. The latter is for Windows Store apps.

To retrieve the settings stored by a WP Silverlight app, we basically have to read and parse the __ApplicationSettings file. A simplistic way to do this would be something like this:

StorageFolder localFolder = Windows.Storage.ApplicationData.Current.LocalFolder;
if (localFolder != null)
{
  StorageFile appSettings = await localFolder.GetFileAsync("__ApplicationSettings");
  if (appSettings != null)
  {
    // Got the file - now try to read it
    XDocument oldSettings = new XDocument();
    using (var readStream = await appSettings.OpenStreamForReadAsync() as Stream)
    {
      using (StreamReader sr = new StreamReader(readStream))
      {
        // Dump the first line - it isn't XML
        sr.ReadLine();
        // Then get the rest in
        oldSettings = XDocument.Load(sr);
      }
    }

    XNamespace xns = "http://schemas.microsoft.com/2003/10/Serialization/Arrays";
    XElement f1 = oldSettings.Root.Element(xns + "KeyValueOfstringanyType");
    var f2 = oldSettings.Descendants(xns + "KeyValueOfstringanyType").ToList();
  }
}

That succeeds in reading in the XML. You’ve then got to iterate through the list, looking for Keys that you are interested in and extracting the Values from the corresponding XML node. For example, here is one node retrieved from my settings file:

<KeyValueOfstringanyType xmlns="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
  <Key>FirstRun</Key>
  <Value xmlns:d3p1="http://www.w3.org/2001/XMLSchema" i:type="d3p1:boolean" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">false</Value>
</KeyValueOfstringanyType>

Things get a bit more challenging if you used a class or other complex type to save away. Thankfully, Pedro Lamas has written a great bit of code that essentially mimics what the Silverlight code does when it reads in the application settings file. So, now, all you need to do is call GetValuesAsync() and you’ll end up with a set of key pairs including any non-standard classes. In my case, that is an ObservableCollection<DatabaseList>.

Now, I did encounter some struggle points while trying to get Pedro’s code to work in my app. The main challenge was around the handling of the first line in the settings file. That line of text (which I was ignoring in my simplistic approach) actually lists out any “non standard” types so that the DataContractSerializer knows how to parse the XML appropriately and rebuild the objects.

So why was I having problems? Here is the first line from my settings file:

System.Collections.ObjectModel.ObservableCollection`1[[Relative_History.DatabaseList, Relative History, Version=1.4.8.0, Culture=neutral, PublicKeyToken=null]], System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e

The problem I was having was that the call to Type.GetType (in Pedro’s code) was returning null because the system couldn’t match the object. There were a couple of reasons why, in my case:

  1. The WP Silverlight app had an assembly name of “Relative History”. In my Universal App project, I had the Win8.1 project set to an assembly name of “RelHist2.Windows” and the WP8.1 project set to an assembly name of “RelHist2.WindowsPhone”.
  2. The version number expected was 1.4.8.0 but my Universal App has a version number of 1.0.0.0.

One work-around I came up with was to replace the section of Pedro’s code where knownTypes is declared with this:

System.Type[] knownTypes = new Type[] { typeof(System.Collections.ObjectModel.ObservableCollection<Relative_History.DatabaseList>) };

This worked but did mean that the code wasn’t then as flexible as it should be. I finally solved the problem by changing the assembly names in my Universal App to match that of the Silverlight app, and increased the version number to be higher than that of the Silverlight app.

One final tweak to Pedro’s code if you are copying/pasting his code rather than using Cimbalino is to change:

public async Task<IEnumerable<KeyValuePair<string, object>>> GetValuesAsync()

to

public async Task<IDictionary<string, object>> GetValuesAsync()

With all of that done, Pedro’s code then makes it much easier to load in the settings and access the ones you want to retain:

                var oldSettings = await GetValuesAsync();
                // Now see which settings we want to retain
                if (oldSettings.ContainsKey("fred"))
                {
                    var value = oldSettings["fred"];
                }

In the next article, I’m going to be looking at handling licencing when moving from WP Silverlight to WP XAML.

 

Advertisements

Fixing the default Windows 8 XAML ItemContainerStyle

One of the things I love about the look of Windows 8 is the little touches of feedback as you navigate around. For example, here is the Messaging icon on the Start screen:

Messaging

If you hover over it on a mouse-based system, you get a little extra border to hint that you can click on it:

Messaging-2

and if you select the icon, you get a different border with an earmarked tick:

Messaging-3

Sweet! So what happens if you try to use this in your own app? Here are the screenshots of a button using the Standard500x130Template in a GridView:

Button

Button-2

Button-3

Now, I don’t consider myself to be a designer but these look pretty ugly to me! If you look at the Standard500x130Template, though, it doesn’t really hint at how it can be made prettier to get it to look more like the Messaging button.

The solution lies with ItemContainerStyle. This is a block of XAML that you can reference from, say, a GridView and it defines what an item is going to look like when it goes through different visual states. The first thing you have to do is use Blend to capture a copy of the default definition by using these steps:

  • Start a new project of type XAML (Windows Store). Select Grid App (XAML).
  • Blend should, by default, open GroupedItemsPage.xaml. If it doesn’t, open it.
  • On the Objects and Timeline pane, open up Grid so that you can see the items defined in the Grid.
  • Right-click on itemGridView and select Edit Additional Templates > Edit Generated Item Container > Edit a Copy:

EditAdditionalTemplate

  • In the window that appears (below), accept the defaults and click on OK:

CreateStyleResource

  • Switch Blend to code view and you should find a style has been added called GridViewItemStyle1. You can copy & paste this either into a central style XAML file for your project or, if only needed on a single page, directly into the Resources section of that page’s XAML.

(If you are struggling with the above steps, you can find the original XAML at the end of this post)

I’ve already mentioned that I’m not a designer, so I don’t pretend to fully understand VisualState or StoryBoard but I’ll work through some of the key elements as I understand them and explain how the rendering of the items works.

Let’s start with what happens when you position the pointer over an item. We’ve seen from the screenshots that a big grey rectangle appears. This happens because the VisualState PointerOver contains the following line:


<DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="PointerOverBorder"/>

If you look further down the XAML, you will see that this is a rectangle with a fill colour of ListViewItemPointerOverBackgroundThemeBrush. What the above animation does is switch the opacity so that it becomes visible.

So why is it a big grey rectangle and not a nice border like with the Messaging icon? The answer lies with another rectangle which, by default, is only shown when the item is selected! This is the SelectionBackground rectangle and it is filled with ListViewItemSelectedBackgroundThemeBrush. I’ll come back to this in a minute.

Now, let’s look in more detail at what happens when the item is selected. This is another VisualState called, sensibly enough, Selected. This changes the opacity of SelectionBackground, SelectedBorder and SelectedCheckMark so that they become visible. We’ve already looked at SelectionBackground, so what about SelectedBorder and SelectedCheckMark?

SelectedBorder is another rectangle that gets drawn around the item with a stroke colour of ListViewItemSelectedBackgroundThemeBrush so that you get a thin, unfilled rectangle.

SelectedCheckMark is a grid consisting of two paths – one drawn with a fill colour of ListViewItemSelectedBackgroundThemeBrush and the other drawn with a fill colour of ListViewItemCheckThemeBrush. The latter is the tick and the former is the corner triangle that is drawn around the tick.

So, all of the pieces of the puzzle are there. Why, then, doesn’t the item get drawn even remotely like the Messaging icon? Let’s look at the Selected visual state again. It causes three items to be displayed but there is a problem with this – the SelectionBackground, as defined in the style, is filled with the same colour as the SelectedBorder and the corner triangle in SelectedCheckMark. That is why the border and triangle don’t show up.

After a bit of thinking about this, I made a couple of changes that actually ended up fixing all of the above problems, so I’ll just share my changes:

  • Change the fill colour of SelectionBackground so that it uses a different colour from ListViewItemSelectedBackgroundThemeBrush. In my case, because my items are being drawn on a white background, I fixed the colour at white … you’ll see why in a minute.
  • Change the opacity of SelectionBackground from 0 to 1 so that it is always visible.

Why make the last change? It turns out that the reason you get a big grey rectangle instead of a nice border hint is because the selection background isn’t visible – remember that I mentioned it only gets switched on when the item is selected? So by forcing it to be visible all of the time, that changes the appearance of that big grey rectangle to a nice border hint.

Here are the screenshots after revising the style:

PointerOver

Selected

Much better!

I don’t know or understand why the default style is defined the way it is, and it may be that the changes I’ve made aren’t the optimal ones but they do seem to get my app to be closer to those released by Microsoft. Once you’ve defined the style, all you need to do is reference it in the GridView or ListView with ItemContainerStyle=”{StaticResource <whatever you called it>}”.

Original GridView item style:

<Style x:Key="GridViewItemStyle1" TargetType="GridViewItem">
<Setter Property="FontFamily" Value="{StaticResource ContentControlThemeFontFamily}"/>
<Setter Property="FontSize" Value="{StaticResource ControlContentThemeFontSize}"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="TabNavigation" Value="Local"/>
<Setter Property="IsHoldingEnabled" Value="True"/>
<Setter Property="Margin" Value="0,0,2,2"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="GridViewItem">
<Border x:Name="OuterContainer">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal"/>
<VisualState x:Name="PointerOver">
<Storyboard>
<DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="PointerOverBorder"/>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Fill" Storyboard.TargetName="SelectionBackground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource ListViewItemSelectedPointerOverBackgroundThemeBrush}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Stroke" Storyboard.TargetName="SelectedBorder">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource ListViewItemSelectedPointerOverBorderThemeBrush}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Fill" Storyboard.TargetName="SelectedEarmark">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource ListViewItemSelectedPointerOverBackgroundThemeBrush}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed">
<Storyboard>
<PointerDownThemeAnimation TargetName="ContentContainer"/>
</Storyboard>
</VisualState>
<VisualState x:Name="PointerOverPressed">
<Storyboard>
<PointerDownThemeAnimation TargetName="ContentContainer"/>
<DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="PointerOverBorder"/>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Fill" Storyboard.TargetName="SelectionBackground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource ListViewItemSelectedPointerOverBackgroundThemeBrush}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Stroke" Storyboard.TargetName="SelectedBorder">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource ListViewItemSelectedPointerOverBorderThemeBrush}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Fill" Storyboard.TargetName="SelectedEarmark">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource ListViewItemSelectedPointerOverBackgroundThemeBrush}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled">
<Storyboard>
<DoubleAnimation Duration="0" To="{StaticResource ListViewItemDisabledThemeOpacity}" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="contentPresenter"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="FocusStates">
<VisualState x:Name="Focused">
<Storyboard>
<DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="FocusVisual"/>
</Storyboard>
</VisualState>
<VisualState x:Name="Unfocused"/>
<VisualState x:Name="PointerFocused"/>
</VisualStateGroup>
<VisualStateGroup x:Name="SelectionHintStates">
<VisualStateGroup.Transitions>
<VisualTransition GeneratedDuration="0:0:0.65" To="NoSelectionHint"/>
</VisualStateGroup.Transitions>
<VisualState x:Name="VerticalSelectionHint">
<Storyboard>
<SwipeHintThemeAnimation ToHorizontalOffset="0" TargetName="SelectionBackground" ToVerticalOffset="15"/>
<SwipeHintThemeAnimation ToHorizontalOffset="0" TargetName="ContentBorder" ToVerticalOffset="15"/>
<SwipeHintThemeAnimation ToHorizontalOffset="0" TargetName="SelectedBorder" ToVerticalOffset="15"/>
<SwipeHintThemeAnimation ToHorizontalOffset="0" TargetName="SelectedCheckMark" ToVerticalOffset="15"/>
<DoubleAnimationUsingKeyFrames Duration="0:0:0.500" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="HintGlyph">
<DiscreteDoubleKeyFrame KeyTime="0:0:0" Value="0.5"/>
<DiscreteDoubleKeyFrame KeyTime="0:0:0.500" Value="0"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="HorizontalSelectionHint">
<Storyboard>
<SwipeHintThemeAnimation ToHorizontalOffset="-23" TargetName="SelectionBackground" ToVerticalOffset="0"/>
<SwipeHintThemeAnimation ToHorizontalOffset="-23" TargetName="ContentBorder" ToVerticalOffset="0"/>
<SwipeHintThemeAnimation ToHorizontalOffset="-23" TargetName="SelectedBorder" ToVerticalOffset="0"/>
<SwipeHintThemeAnimation ToHorizontalOffset="-23" TargetName="SelectedCheckMark" ToVerticalOffset="0"/>
<DoubleAnimationUsingKeyFrames Duration="0:0:0.500" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="HintGlyph">
<DiscreteDoubleKeyFrame KeyTime="0:0:0" Value="0.5"/>
<DiscreteDoubleKeyFrame KeyTime="0:0:0.500" Value="0"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="NoSelectionHint"/>
</VisualStateGroup>
<VisualStateGroup x:Name="SelectionStates">
<VisualState x:Name="Unselecting">
<Storyboard>
<DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="HintGlyphBorder"/>
</Storyboard>
</VisualState>
<VisualState x:Name="Unselected">
<Storyboard>
<DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="HintGlyphBorder"/>
</Storyboard>
</VisualState>
<VisualState x:Name="UnselectedPointerOver">
<Storyboard>
<DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="HintGlyphBorder"/>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="contentPresenter">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource ListViewItemSelectedForegroundThemeBrush}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="UnselectedSwiping">
<Storyboard>
<DoubleAnimation Duration="0" To="0.5" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="SelectingGlyph"/>
<DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="HintGlyphBorder"/>
</Storyboard>
</VisualState>
<VisualState x:Name="Selecting">
<Storyboard>
<DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="SelectionBackground"/>
<DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="SelectedBorder"/>
<DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="SelectingGlyph"/>
<DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="HintGlyphBorder"/>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="contentPresenter">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource ListViewItemSelectedForegroundThemeBrush}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Selected">
<Storyboard>
<DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="SelectionBackground"/>
<DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="SelectedBorder"/>
<DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="SelectedCheckMark"/>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="contentPresenter">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource ListViewItemSelectedForegroundThemeBrush}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="SelectedSwiping">
<Storyboard>
<DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="SelectionBackground"/>
<DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="SelectedBorder"/>
<DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="SelectedCheckMark"/>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="contentPresenter">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource ListViewItemSelectedForegroundThemeBrush}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="SelectedUnfocused">
<Storyboard>
<DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="SelectionBackground"/>
<DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="SelectedBorder"/>
<DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="SelectedCheckMark"/>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="contentPresenter">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource ListViewItemSelectedForegroundThemeBrush}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="DragStates">
<VisualStateGroup.Transitions>
<VisualTransition GeneratedDuration="0:0:0.2" To="NotDragging"/>
</VisualStateGroup.Transitions>
<VisualState x:Name="NotDragging"/>
<VisualState x:Name="Dragging">
<Storyboard>
<DoubleAnimation Duration="0" To="{StaticResource ListViewItemDragThemeOpacity}" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="InnerDragContent"/>
<DragItemThemeAnimation TargetName="InnerDragContent"/>
<FadeOutThemeAnimation TargetName="SelectedCheckMarkOuter"/>
<FadeOutThemeAnimation TargetName="SelectedBorder"/>
</Storyboard>
</VisualState>
<VisualState x:Name="DraggingTarget">
<Storyboard>
<DropTargetItemThemeAnimation TargetName="OuterContainer"/>
</Storyboard>
</VisualState>
<VisualState x:Name="MultipleDraggingPrimary">
<Storyboard>
<DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="MultiArrangeOverlayBackground"/>
<DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="MultiArrangeOverlayText"/>
<DoubleAnimation Duration="0" To="{StaticResource ListViewItemDragThemeOpacity}" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="ContentBorder"/>
<FadeInThemeAnimation TargetName="MultiArrangeOverlayBackground"/>
<FadeInThemeAnimation TargetName="MultiArrangeOverlayText"/>
<DragItemThemeAnimation TargetName="ContentBorder"/>
<FadeOutThemeAnimation TargetName="SelectionBackground"/>
<FadeOutThemeAnimation TargetName="SelectedCheckMarkOuter"/>
<FadeOutThemeAnimation TargetName="SelectedBorder"/>
<FadeOutThemeAnimation TargetName="PointerOverBorder"/>
</Storyboard>
</VisualState>
<VisualState x:Name="MultipleDraggingSecondary">
<Storyboard>
<FadeOutThemeAnimation TargetName="ContentContainer"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="ReorderHintStates">
<VisualStateGroup.Transitions>
<VisualTransition GeneratedDuration="0:0:0.2" To="NoReorderHint"/>
</VisualStateGroup.Transitions>
<VisualState x:Name="NoReorderHint"/>
<VisualState x:Name="BottomReorderHint">
<Storyboard>
<DragOverThemeAnimation Direction="Bottom" ToOffset="{StaticResource ListViewItemReorderHintThemeOffset}" TargetName="ReorderHintContent"/>
</Storyboard>
</VisualState>
<VisualState x:Name="TopReorderHint">
<Storyboard>
<DragOverThemeAnimation Direction="Top" ToOffset="{StaticResource ListViewItemReorderHintThemeOffset}" TargetName="ReorderHintContent"/>
</Storyboard>
</VisualState>
<VisualState x:Name="RightReorderHint">
<Storyboard>
<DragOverThemeAnimation Direction="Right" ToOffset="{StaticResource ListViewItemReorderHintThemeOffset}" TargetName="ReorderHintContent"/>
</Storyboard>
</VisualState>
<VisualState x:Name="LeftReorderHint">
<Storyboard>
<DragOverThemeAnimation Direction="Left" ToOffset="{StaticResource ListViewItemReorderHintThemeOffset}" TargetName="ReorderHintContent"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="DataVirtualizationStates">
<VisualState x:Name="DataAvailable"/>
<VisualState x:Name="DataPlaceholder">
<Storyboard>
<ObjectAnimationUsingKeyFrames Duration="0" Storyboard.TargetProperty="Visibility" Storyboard.TargetName="PlaceholderTextBlock">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Visible</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Duration="0" Storyboard.TargetProperty="Visibility" Storyboard.TargetName="PlaceholderRect">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Visible</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid x:Name="ReorderHintContent" Background="Transparent">
<Path x:Name="SelectingGlyph" Data="F1 M133.1,17.9 L137.2,13.2 L144.6,19.6 L156.4,5.8 L161.2,9.9 L145.6,28.4 z" Fill="{StaticResource ListViewItemCheckSelectingThemeBrush}" FlowDirection="LeftToRight" HorizontalAlignment="Right" Height="13" Margin="0,9.5,9.5,0" Opacity="0" Stretch="Fill" VerticalAlignment="Top" Width="15"/>
<Border x:Name="HintGlyphBorder" HorizontalAlignment="Right" Height="40" Margin="4" Opacity="0" VerticalAlignment="Top" Width="40">
<Path x:Name="HintGlyph" Data="F1 M133.1,17.9 L137.2,13.2 L144.6,19.6 L156.4,5.8 L161.2,9.9 L145.6,28.4 z" Fill="{StaticResource ListViewItemCheckHintThemeBrush}" FlowDirection="LeftToRight" HorizontalAlignment="Right" Height="13" Margin="0,5.5,5.5,0" Opacity="0" Stretch="Fill" VerticalAlignment="Top" Width="15"/>
</Border>
<Border x:Name="ContentContainer">
<Grid x:Name="InnerDragContent">
<Rectangle x:Name="PointerOverBorder" Fill="{StaticResource ListViewItemPointerOverBackgroundThemeBrush}" IsHitTestVisible="False" Margin="1" Opacity="0"/>
<Rectangle x:Name="FocusVisual" IsHitTestVisible="False" Opacity="0" Stroke="{StaticResource ListViewItemFocusBorderThemeBrush}" StrokeThickness="2"/>
<Rectangle x:Name="SelectionBackground" Fill="{StaticResource ListViewItemSelectedBackgroundThemeBrush}" Margin="4" Opacity="0"/>
<Border x:Name="ContentBorder" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Margin="4">
<Grid>
<ContentPresenter x:Name="contentPresenter" ContentTransitions="{TemplateBinding ContentTransitions}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
<TextBlock x:Name="PlaceholderTextBlock" Foreground="{x:Null}" IsHitTestVisible="False" Margin="{TemplateBinding Padding}" Text="Xg" Visibility="Collapsed"/>
<Rectangle x:Name="PlaceholderRect" Fill="{StaticResource ListViewItemPlaceholderBackgroundThemeBrush}" IsHitTestVisible="False" Visibility="Collapsed"/>
<Rectangle x:Name="MultiArrangeOverlayBackground" Fill="{StaticResource ListViewItemDragBackgroundThemeBrush}" IsHitTestVisible="False" Opacity="0"/>
</Grid>
</Border>
<Rectangle x:Name="SelectedBorder" IsHitTestVisible="False" Margin="4" Opacity="0" Stroke="{StaticResource ListViewItemSelectedBackgroundThemeBrush}" StrokeThickness="{StaticResource GridViewItemSelectedBorderThemeThickness}"/>
<Border x:Name="SelectedCheckMarkOuter" HorizontalAlignment="Right" IsHitTestVisible="False" Margin="4" VerticalAlignment="Top">
<Grid x:Name="SelectedCheckMark" Height="40" Opacity="0" Width="40">
<Path x:Name="SelectedEarmark" Data="M0,0 L40,0 L40,40 z" Fill="{StaticResource ListViewItemSelectedBackgroundThemeBrush}" Stretch="Fill"/>
<Path Data="F1 M133.1,17.9 L137.2,13.2 L144.6,19.6 L156.4,5.8 L161.2,9.9 L145.6,28.4 z" Fill="{StaticResource ListViewItemCheckThemeBrush}" FlowDirection="LeftToRight" HorizontalAlignment="Right" Height="13" Margin="0,5.5,5.5,0" Stretch="Fill" VerticalAlignment="Top" Width="15"/>
</Grid>
</Border>
<TextBlock x:Name="MultiArrangeOverlayText" Foreground="{StaticResource ListViewItemDragForegroundThemeBrush}" FontSize="26.667" FontFamily="{StaticResource ContentControlThemeFontFamily}" IsHitTestVisible="False" Margin="18,9,0,0" Opacity="0" TextWrapping="Wrap" Text="{Binding TemplateSettings.DragItemsCount, RelativeSource={RelativeSource Mode=TemplatedParent}}" TextTrimming="WordEllipsis"/>
</Grid>
</Border>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

Win8 development: using the Multilingual App Toolkit

The Multilingual App Toolkit (or MAT for short!) integrates into Visual Studio 2012 and is intended to make it easy to manage the translation of strings through features such as import & export of translations and the use of Microsoft Translator to automate some of the processes.

There are some good videos (http://go.microsoft.com/fwlink/?LinkId=266600, http://go.microsoft.com/fwlink/?LinkId=266603 and http://go.microsoft.com/fwlink/?LinkId=266604) and articles (http://msdn.microsoft.com/en-us/library/windows/apps/xaml/JJ572370(v=win.10).aspx and http://msdn.microsoft.com/en-us/library/windows/apps/xaml/hh965329.aspx) on how to use MAT but I still couldn’t get my app to use the translated strings. The app continued to use the strings that I was putting into my English resource file.

Here is the answer: you must mark each and every string as Signed off in the Multilingual Editor (so that the blob on the left hand side of the window goes green) before those strings are used. Once you’ve done that, you should then see the strings being used so long as you’ve set your display language appropriate in Windows.

 

Win8 Development: getting icons

One of the significant improvements from developing for the Windows Phone platform is that Windows 8 supports XAML as an image type, allowing you to provide vector graphics rather than rasterised. This ensures that you get the crispest, cleanest iconography you can have because the OS will scale the images appropriately.

One of the sites that I’ve used in the past is the Noun Project. They have some stunning icons, all of which can be downloaded in SVG format … but how to then get that into XAML?

The simplest method I’ve found so far is Mike Swanson’s free Adobe Illustrator to XAML Export plug-in. Download, copy to the right directory, open the SVG file in AI, choose Export > XAML.

Job done.

Well, almost. You’ve then got to incorporate that into the project as a resource, but that’s for another blog ;-).

 

Win8 Development: major gotcha in page navigation

One of the major differences in page navigation between Windows Phone 7 and Windows 8 “Modern UI” apps is that the latter allows you to pass an object to the page whereas Windows Phone 7 is pretty much limited to simple items because navigation is done in the form of a URL.

Unfortunately, it turns out that while passing objects to a page does work, it causes a problem with the SuspensionManager because the object cannot be serialized. If you try, the call that SuspensionManager makes to Frame.GetNavigationState() results in an exception.

This took me a while to figure out (mainly because I’d forgotten that I’d been extending my code by passing objects to the pages) but also because I didn’t read the debug output closely enough to see this message:

WinRT information: GetNavigationState doesn’t support serialization of a parameter type which was passed to Frame.Navigate.

So, the upshot is that if you’ve written a Windows Phone app, you can pretty much stick to the same navigation methodology, passing simple objects to the page.

Reference: Microsoft Connect

How to inspect SQLite databases?

For the purposes of looking at the databases that my fledgling Windows 8 app creates, I’ve decided to try SQLite Administrator: http://sqliteadmin.orbmu2k.de/. This is a free tool that allows you to enter SQL queries to execute against the database. It means I need to brush up on my SQL but the tool isn’t too bad. Depending on how much I end up needing to look at the data, I may decide to try SQLite Spy (http://www.yunqa.de/delphi/doku.php/products/sqlitespy/index) which was another tool suggested by a discussion on StackOverflow, which in turn also references a big list of tools on SQLite’s own web site … so my journey to find a nice tool may not end here …

Win8 Development: coping without EntityRef and EntitySet

In a recent post, I mentioned that the version of the .Net framework being used by Windows Store apps doesn’t have any support for EntityRef and EntitySet. I have used these extensively in my WP app to link database tables together. I posted on StackOverflow to see if there were any suggestions and one was to use System.Data.SQLite, which provides ADO.NET interfaces to SQLite. However, I was put off this suggestion for a few reasons:

  1. The FAQ says that all System.Data.SQLite objects that implement IDisposable, either directly or indirectly, should be explicitly disposed when they are no longer needed in order to avoid memory leaks. The way it was worded was a bit off-putting in as much as how am I supposed to figure out which objects implement IDisposable, particularly indirectly?
  2. There doesn’t appear to be a WinRT version yet. There are 32-bit and 64-bit Windows versions but what about ARM?
  3. Would this work with SQLite-net or instead of? SQLite-net has good support for asynchronous working which may be lost if this works instead of that library.

So, in the end, I’ve decided to take a simpler approach and deal with it by hand. Where a child table is linked to a parent table, the child has an extra row defined that is a nullable int to store the ID for that parent table. Then, in the class for the parent table, I define an “Add” function like this:

public ChildClass Add(ChildClass child)
{
    Debug.Assert(this.ID != 0);
    child.ParentClass = this.ID;
    return child;
}

The purpose of the Assert is to make sure that the parent class has been inserted into the database and therefore has its primary key column set. In my code, when I want to create a new child class, I have a routine called AddChild which then returns the new child object. Because the above Add routine returns the class that is passed to it, this allows me to go:

_db.Update(_parent.Add(AddChild(parameters)));

The AddChild routine creates a new instance of the Child class and then calls _db.Insert(_child) so that the Child instance is added to the database and gets it’s ID value. The rest of AddChild does other bits to the members of the class but doesn’t call _db.Update. I rely on the above line to do the setting of the parent’s ID and calling Update all in one go so that writes to the database are minimised.

The above works but isn’t ideal. One way in which EntityRef and EntitySet are clearly better is that they enforce the correct class usage. For example, if the Child class could be linked to Parent and StepParent, my method wouldn’t do anything to stop me inadvertently setting the child’s ParentClass value to the ID of the StepParent class if I got my logic wrong somewhere. EnttiyRef/EntitySet would handle that because of the type linkage.

Win8 Development: Stumbling Block #1

This could be a bit of a show-stopper but Windows Store apps have their own flavour of .NET – yes, yet another variant of the framework and it seems even more restrictive than the Silverlight version that Windows Phone has.

The stumbling block in my case is the complete absence of EntityRef and EntitySet. These are used extensively in my WP app to link tables together and I’m struggling to figure out how to get the code to work without them. I’m still searching …

Windows 8 Development

Something I had intended to do while I was working on my first Windows Phone app was to keep track of web sites/pages/blogs that were helping me along the way, as well as snippets of knowledge that I figured out to solve a problem.

Well, that didn’t happen, did it!?!?

So, now that the first Phone app is done and dusted, I’m turning my attention to my first “Modern UI” app (or whatever Microsoft are calling this week). The app will rely on a database, something that isn’t supported natively by Windows 8, so that is where I’m starting.

The proposed solution for programmers requiring a database is SQLite. This, like SQL CE, is not a client/server solution but is, instead, providing database-aspects on top of a single file. From what I’ve read about SQLite, it looks to be a big improvement over SQL CE so I can see why Microsoft are recommending it rather than baking their own.

To get started, I’m following the instructions in a blog posting by Tim Heuer. He documents the steps required to install SQLite then configure your project to use the DLL then incorporate a LINQ wrapper.

I can see that I’ve got quite a learning curve ahead of me, though. Apart from anything else, moving from an environment where you can build for “Any CPU” to one where you have to essentially build three times (x86, x64 and ARM) means learning more about Visual Studio (some might say I ought to know these bits anyway) and more testing/debugging.

Fun times ahead!