DevCenter Promo Codes Not Working?

One of the great things about the new DevCenter is the ability to generate Promotional codes for your in-app-purchase products, so I generated 100 codes last night for the launch of Windows 10.

I gave out many codes today but I started getting “the promo code didn’t work” emails. After a quick investigation I found that the LicenseInformation for the user wasn’t refreshed automatically or even after the user restarted their phone. I suspect that this is just temporary, but I found a workaround…

The trick is to have the user go through the process to purchase the IAP product. The user’s phone will do a license verify check with the Store server and show this screen:

Already Owned

 

Normally, if they did not own the product there would be a payment method and a “buy” button. However, since they redeemed your code, the button will be labeled “install” as seen in this screenshot:

2015-07-29_1516

Just tell your user to click “Install” and go on experiencing your awesome app!

If you have any questions, feel free to leave a comment below or ping me on twitter

Lance

 

One XAML for UWP, Windows 8.1 and Windows Phone 8.1

I was recently involved in a conversation on how to have the easiest way to maintain a XAML view across a UWP (Universal Windows Project) a Windows 8.1 and Windows Phone 8.1 projects. There are a few options and the most straight forward way to do it with a UserControl residing in a Portable Class Library. However…

What if you wanted to have tailored code for each without littering your code with #ifdef but still share a XAML view?  The XAML View might be what you’re looking for. This is a tutorial on how to do just that. An example project is available for download at the end of the article. Let’s get started:

Step 1:

Create a new 8.1 Universal app

tpx1

Step 2:

Move the Shared, Windows and Windows Phone projects out of the virtual folder and delete the folder (you can cut/paste or just click and drag them). The solution should look like this now

tpx2

(Note: If you’re doing this to a solution that has many other projects, you might want to skip this step and add the UWP project to the virtual folder instead)

Step 3:

Add a new UWP project to the solution and name it the same as the 8.1 app, but with the Universal suffix.

tpx3

(Your solution should look like this now)

tpx4

Step 4:

Add a “Views” folder to each of the projects

tpx5

Step 5:

Within the Universal project, right click and Add > New Item > XAML View

tpx6

Step 6:

Move the new XAML View to the Shared project’s Views folder and change the namespaces in the view to match

tpx7

Step 7:

Delete App.xaml from the Universal project and add a reference to the solution’s Shared project (Note: this is in the new Shared projects references section)

tpx8

Step 8:

Here’s where the magic happens. We’ll be adding a code behind for this view in each of the projects! I’ll break this down into sub-steps:

  1. Add a new class to the Windows 8.1 project’s Views folder (Add > New Item), name it as if it were the code-behind for the view. In this case it would be SharedPage.xaml.cs
  2. Change the namespace of the class to Views
  3. Add the public, sealed and partial modifiers to the class
  4. You’ll next need to inherit from the Page class
  5. Add a page constructor
  6. Now you can copy and paste this new class into each of the platform projects (remember, we do not need it in the Shared project)

This is what it should look like

tpx9

Step 9:

You’ll need to quickly pop into the Build Configuration Manager and check off Build and Deploy for the Universal app (you can find Configuration Manager in the target dropdown or in the Build menu)

tpx10

Step 10:

Lastly, for the purposes of this demo, go to App.xaml.cs and change the initial launch target (MainPage) to be the new shared page (SharedPage). I could have put a button on MainPage for each app, but let’s keep this tutorial as short as possible.

tpx11

Final result!

This is the same XAML View compiled with different code-behind files 🙂

tpx12

(NOTE: I put a TextBlock on the SharedPage and update the text in each constructor to show which platform launched it. Here are the WP8.1 emulator, Windows 10 PC and Windows 10 Mobile Emulator running their apps all showing the same XAML view).

Source Code

Download the Sample App Source Code From Here

Bonus:

The Telerik Universal Control can be used in the shared page as long as each of the projects have a reference to the Telerik UYI for Windows Universal DLLs. Send me a tweet and show me what you’ve done, I’ll RT your awesomeness!

Custom Pivot Header with Animation

I recently wanted to make a header with tabs for my app’s pages that have a Pivot. Something like Office Mobile, but without the drop-down menus. Here’s the result I got in my upcoming app. I decided to post a tutorial and provide a sample app.

CustomPivotHeader

 

Notice the fast fade-in of the background color of the tab, this is important and is where you’ll be able to add your own flavor to the style after you’ve completed this tutorial. Ok, let’s get started!

Step One: Create the base elements

The two main components are a Pivot control and a ListView control. The Pivot has been stripped of it’s title template and pivot header templates. To get started, let’s do a File > New Pivot App (WinRT, not Silverlight) so that we’ll have some sample data and a pre-existing Pivot.

StepOne1

After the project template finishes, open PivotPage.XAML and add RequestedTheme=”Light” to the page’s properties. Next, find the root grid of the page. Add a couple RowDefinitions, with the first row’s height set to auto. Add a Grid containing a ListView to Row 0 and put the Pivot into Row 1.

StepOne2

Now, let’s clean up the pivot. Delete the Pivot’s Title and both the PivotItem’s Header properties. You should be left with only the pivot item’s contents, this is what your page should look like at this point.

StepOne3

Step Two: Create a Control for the Tabs

My demo uses text, however there are other approaches that can use an icon or other element in the tab. Since not all XAML elements have a “Foreground” property that can automatically inherit from the parent ListView’s foreground, we’ll use a  container control to hold the TextBlock. Make this by right clicking on your project and select Add > New Item. Then find Templated Control and give it the name HeaderTab.cs.

StepTwo1

A template control has a backing style where the UI is defined while the control’s logic is in the file named after it. Visual Studio will add a folder named Themes and a ResourceDictionary Generic.xaml.

StepTwo2

First, Open HeaderTab.cs and change the base class from Control to ContentControl. This will allow you to use the control as a ContentControl, which is what the ListViewItem’s template uses.

StepTwo4

Next, open Generic.xaml, ignore the errors for now, they will go away when you do a Build at the end of this step. First, replace the Border control in the style with a TextBlock. Now, use TemplateBindings for the Text and Margin properties (see screenshot). This is how we pass the properties values of the ListView ItemContainerStyle to our custom control when the property types to match. The Margin property is a perfect example, we use the padding of the container style for the margin of the TextBlock, this will make more sense towards the end of the tutorial. Okay, now it’s time to do a Build (F6) so that your style’s TargetType will resolve.

This is what your Style should look like:

StepTwo3

Step Three: Create a horizontal ItemsPanel

In order to tell the ListView to render the items horizontally, we need an ItemsPanel, however since we want the content of the tab to be in the center but also stretch to fill the available space, we can’t use a simple StackPanel. So, let’s make our own. Right click on your project and select Add > New > Class and name it HorizontalStretchPanel.

StepThree1

Explaining the process of calculating the available space and arranging the items is outside the scope of this article, but in a nutshell, we take the full width and divide it by the number of items then arrange to get the most space for each item. Here’s the code to copy/paste:


public class HorizontalStretchPanel : Panel
{
protected override Size ArrangeOverride(Size finalSize)
{
var rect = new Rect(0, 0, finalSize.Width, finalSize.Height);
var width = finalSize.Width / Children.Count;

foreach(var tab in Children)
{
rect.Width = width;
rect.Height = tab.DesiredSize.Height > finalSize.Height ? tab.DesiredSize.Height : finalSize.Height;
tab.Arrange(rect);
rect.X = width + rect.X;
}

return finalSize;
}

protected override Size MeasureOverride(Size availableSize)
{
if(Children.Count == 0)
return base.MeasureOverride(availableSize);

var finalSize = new Size { Width = availableSize.Width };
availableSize.Width = availableSize.Width / Children.Count;

foreach(var tab in Children)
{
tab.Measure(availableSize);
var desiredSize = tab.DesiredSize;
finalSize.Height = desiredSize.Height > finalSize.Height ? desiredSize.Height : finalSize.Height;
}

if(double.IsPositiveInfinity(finalSize.Height) || double.IsPositiveInfinity(finalSize.Width))
return Size.Empty;

return finalSize;
}
}

 

Step Four: Create a ListView Configuration and ItemContainerStyle

Now it’s time to go back to the ListView we added to the top of PivotPage.xaml . Before working on the ListView, Give the parent Grid a height of 50 and a good background that will contrast with white, I went with Blue. Now, onto the ListView. Let’s set the ListView.ItemsPanel to use our new HorizontalStretchPanel. Next, add some ListViewItems containing your new HeaderTab control. You’ll want one ListViewItem for each PivotItem you have. While you’re there, set the FontSize of your HeaderTab to 20.

Now, bind the SelectedIndex of the ListView to the SelectedIndex of the Pivot using an ElementName binding and set VerticalAlignment to bottom.

Here’s what it should look like thus far

StepFour1

Now, it’s time to add some style and animation to the ListViewItemContainer. To begin, extract the ListView’s default ItemContainerStyle, this screenshot shows how:

StepFour2

Give a name, I chose HeaderListViewItemContainerStyle, once you click Ok, the ListView will get a StaticResource reference to the style in the page’s Resources. Scroll up to the top of the page and expand the style. Yeah, it’s pretty long. the part I want you to get to is the Template property. Within here you’ll see some animations, but go past them until you see the ContentControl. This is what shows your HeaderTab control, I like to give my template parts names with strong prefixes, you don’t have to, but it’s easier for identification when it comes to animation.

Now, let’s edit that template to add an extra Grid so we can act on it to get some cool fading animation when the user changes tabs. What we’re going to do is put the new Grid behind the ContentControl so that we don’t block the Text. To make this easier, here is what the XAML looks like after renaming the parts and adding the Grid.

StepFour3

Lastly, I went with White for the Style’s foreground property, this gets inherited by the TextBlock in your HeaderTab control. It will contrast well against the Blue background of the page header Grid.

Step Five: Animating the Container’s Parts

This is something that you’ll want to play with and where Blend can help you get the exact results you’re looking for. What we’re going to do is add some keyframes to the existing States: UnselectedSelected and SelectedFocused. Here’s where the string naming of the template parts comes in handy. First, in the Unselected state we want to style it they way we want it to look when the tab is not in focus. In this state I want my new Grid to have zero height. Here’s what that looks like:

StepFive1

Now let’s go to the Selected and SelectedFocused states (they’re the same in my scenario). In this state I want the new Grid to be the full height of the tab and more importantly to have a white background.

StepFive2

Lastly, the sugar that adds the magic… the transition animation. The cool thing about states is that you don’t have to write long storyboards, just set a Default Transition for a particular state. You can add these right to the VisualStageGroups directly (don’t forget to add some Easing). Here’s what it looks like

StepFive3

 

Almost done! Go through the Pivot and PivotItems and delete all the x:UID properties, these will change your UI at runtime because of localization, best to get them out of the way now. Whew! now it’s time to fire up the emulator and take it for a spin. This is what you should be seeing, if not, download the sample app from here and see what went wrong.

Happy coding!

FinalDemoResult

 

WinRT MediaCapture Tips

As we approach Windows 10, many of you are considering updating your SL 8.0 apps to WinRT. In fact, Larry Lieberman and team recommend you do this and have shared some resources to help facilitate the move. I’ve done this for a couple apps so far and wanted to share some of my experience while migrating Silverlight AudioVideoCaptureDevice API to WinRT MediaCapture, because you’ll need to rewrite your approach.

The WinRT documentation helps with a lot of stuff, but there are holes that I had to discover for myself. To help ease the process, I’m sharing some of the solutions that I’ve discovered, uncovered and smash-my-head-on-the-desk about. Let’s get started:

MediaCapture class

This is your home base of media capture operations. Since it is a better description of what the class does, you’ll see name “mediaCaptureManager” used often. You’ll see it used throughout my code below (before starting, see the “gotchas” Suspension section).

Enumerating Devices (i.e. get front camera)

To get the current video devices attached to the device, first you need to enumerate over the phone/pc’s available video devices using the DeviceClass enum. The user’s device might be a desktop PC with a webcam, it could be a Surface Pro or a Lumia 520, you need to consider the possibilities and be prepared for them.

mediaCaptureManager = new MediaCapture(); //class scope
var devices = await DeviceInformation.FindAllAsync(DeviceClass.VideoCapture);

So instead of the old way of looking for the camera by name { i.e. if(deviceName.Contains(“front”) || deviceName.Contains(“ffc”)) }, you can now use the EnclosureLocation enum. I like to hold the results in a class-wide DeviceInformation object, one for the front cam and one for the rear (rear is also my default to catch webcams and the like), this lets me quickly switch later without having to reiterate over the list. Once you have your chosen camera, use it to initialize the MediaCapture object. You could use a switch statement like this:

foreach (var device in devices)
{
    switch(device.EnclosureLocation.Panel)
    {
    case Windows.Devices.Enumeration.Panel.Front:
        frontCamera = device; //frontCamera is of type DeviceInformation
        isUsingFrontCam = true;
        break;
    case Windows.Devices.Enumeration.Panel.Back:
        rearCamera = device; //rearCamera is of type DeviceInformation
        break;
    default:
        //you can also check for Top, Left, right and Bottom
        break;
    }
}

await mediaCaptureManager.InitializeAsync(new MediaCaptureInitializationSettings { VideoDeviceId = frontCamera.Id });

You have many MediaCaptureInitialization parameters available, but you only need the Id to start the camera. WARNING: If the device is using an attached WebCam (i.e. USB camera), EnclosurePanel will be null. Check for a valid device.Name.

MediaCapture Properties and Showing Preview

Next you want to consider the sensor rotation of the camera. If it is the front camera, you need to rotate it 270 degrees. This used to be a HUGE problem where you had to apply a transform to the UI control that is using the VideoBrush and again on the playback page. Since this only worked on the device, if you viewed the file on another device, it would still be rotated!!!

Thanks to WinRT’s VideoRotation enum, you can rotate the frames for both previewing and recording frames. This is also the time to hook into the following events: Failed (obvious) and RecordLimitationExceeded (save the video and let user know it got cut short).


if(!string.IsNullOrEmpty(mediaCaptureManager.MediaCaptureSettings.VideoDeviceId) && !string.IsNullOrEmpty(mediaCaptureManager.MediaCaptureSettings.AudioDeviceId))
{
   //rotate the video feed according to the sensor
    mediaCaptureManager.SetPreviewRotation(VideoRotation.Clockwise270Degrees);
    mediaCaptureManager.SetRecordRotation(VideoRotation.Clockwise270Degrees);

    //hook into MediaCapture events
    mediaCaptureManager.RecordLimitationExceeded += RecordLimitationExceeded;
    mediaCaptureManager.Failed += Failed;

    //device initialized successfully
    }
    else
    {
    //no cam found
    }
}

Now that you have the device initialized and any advanced properties set, it’s time to push frames to the UI. Here is the most straightforward way:


VideoCaptureElement.Source = mediaCaptureManager;
await mediaCaptureManager.StartPreviewAsync();

//video frames are being pushed to the CaptureElement (instantiated in XAML)

Switching Cameras and Sensor rotation

Now that CaptureElement is showing the video preview, let’s say you want to change cameras. You have to consider two main considerations: stopping current preview and setting up the next device. Here is how I do it (note that I am using Portrait orientation for this page)


private async Task SwitchCameras()
{
   await mediaCaptureManager.StopPreviewAsync();
   mediaCaptureManager.Dispose();
   mediaCaptureManager = null;
   mediaCaptureManager = new MediaCapture();

   if (isUsingFrontCam)
   {
      await mediaCaptureManager.InitializeAsync(new MediaCaptureInitializationSettings { VideoDeviceId = rearCamera.Id });

      mediaCaptureManager.SetRecordRotation(VideoRotation.Clockwise90Degrees);
      mediaCaptureManager.SetPreviewRotation(VideoRotation.Clockwise90Degrees);
   }
   else
   {
      await mediaCaptureManager.InitializeAsync(new MediaCaptureInitializationSettings { VideoDeviceId = frontCamera.Id });

      mediaCaptureManager.SetRecordRotation(VideoRotation.Clockwise270Degrees);
      mediaCaptureManager.SetPreviewRotation(VideoRotation.Clockwise270Degrees);
   }

   isUsingFrontCam = !isUsingFrontCam;

   PreviewMediaElement.Source = mediaCaptureManager;
   await mediaCaptureManager.StartPreviewAsync();
}

Disabling Screen Timeout

One thing you might not realize until you’ve gotten user feedback is the screen timeout. You do not want the user’s device to lock on them while they’re recording (or playing) media. This is accomplished with a DisplayRequest. One word of caution, make sure you are releasing the request when done or other unexpected app close. There have been reports (unconfirmed, but worth consideration) that this API is causing problems with the power button on user’s phones.

Here is how I do it:


//on the class level
private DisplayRequest dRequest;

//in your OnNavigatedTo event
if (dRequest == null)
{
   //disables timeout
   dRequest = new DisplayRequest();
   dRequest.RequestActive();
}

//IMPORTANT! In your OnNavigatedFrom (or other last opportunity)
if (dRequest != null)
{
   dRequest.RequestRelease();
   dRequest = null;
})

Available Resolutions and Frame Rates

A full explanation is outside the scope of this article, however a high overview will help. Essentially, every video capture device reports it’s available resolutions (via firmware) to the OS. Here is a snippet from my app where I get all the available resolutions for the user’s cameras. This is so the user can select a preferred option, this is especially helpful for me because lower memory phones don’t have the horse power to process all the MFT frames (video effects). A lower frame rate allows me to provide a better end user experience for those users.

In this sample, I iterate over the options, save a pointer to each in my ViewModel via a custom object and use it later for when the user selects an option.


var mediaCaptureManager = new MediaCapture();
var devices = await DeviceInformation.FindAllAsync(DeviceClass.VideoCapture);

//GET CAMERAS HERE- same approach to get cameras as at the beginning of this article

if(rearCamera != null)
{ 
   await mediaCaptureManager.InitializeAsync(new MediaCaptureInitializationSettings { VideoDeviceId = rearCamera.Id });
   var mediaEncodingPropertiesList = mediaCaptureManager.VideoDeviceController.GetAvailableMediaStreamProperties(MediaStreamType.VideoPreview);

   if(AvailableResolutions.Count > 0) AvailableResolutions.Clear();

   if (mediaEncodingPropertiesList.Count >= 1)
   {
       foreach (var mediaEncodingProperties in mediaEncodingPropertiesList)
       {
         //I store list in custom collection and let user pick preferred item
         AvailableResolutions.Add(await CreateUserResolutionPropertyAsync((VideoEncodingProperties)mediaEncodingProperties));
       }
    }
}

//if front camera available
if(hasFrontCamera)
 {
    mediaCaptureManager.Dispose();
    mediaCaptureManager = null;
    mediaCaptureManager = new MediaCapture();

    if(AvailableFrontResolutions.Count > 0) AvailableFrontResolutions.Clear();

    await mediaCaptureManager.InitializeAsync(new MediaCaptureInitializationSettings { VideoDeviceId = frontCamera.Id });

    var frontPropertiesList = mediaCaptureManager.VideoDeviceController.GetAvailableMediaStreamProperties(MediaStreamType.VideoPreview);

    if(frontPropertiesList.Count >= 1)
    {
       foreach(var mediaEncodingProperties in frontPropertiesList)
       {
         AvailableFrontResolutions.Add(await CreateUserResolutionPropertyAsync((VideoEncodingProperties)mediaEncodingProperties));
       }
    }
}

I store the user’s selected preference and use it when setting up the camera. If you’re doing this and get stuck, shoot me an email and I’ll share my approach with you.

Gotchas

Thumbnail

For some reason, when saving an .mp4 file created by the MediaCapture API, the file has a 0 length thumbnail. So, if you try to use GetThumbnailAsync on the saved file is a no-go. To workaround this on Phone, I use the Windows Phone MediaComposition API to create the final file that contains a valid thumbnail.

For Windows 8.1, I use the MediaCapture API itself to take a photo at the beginning of the video. I have reported this to the proper people, hopefully it will be fixed in Windows 10.

Suspension

In order to properly handle suspension, it is recommended that you have a handle in App.xaml.cs for the MediaCapture object. This will let you manage it’s state properly when Resuming. For example, after newing-up, in the view do this:


MediaCapture mediaCaptureManager = new MediaCapture();

(App.Current as App).MediaCapture = mediaCaptureManager;

Conclusion

There are a lot of cool things you can do with the new MediaCapture API, the approach above is just my first attempt. I’m sure I’ll continue tweaking it to get the best performance. The lesson learned? It was completely worth the effort to migrate to WinRT.

To see what I’ve done so far, check out my app Video Diary (WP 8.1 or above) http://bit.ly/video-diary ( try the real-time effects, editing and next update will include user settable resolutions and framerates )

Read-only Address Bar for Webview

If you are having a Windows Store application fail certification or being unpublished because you have violated Policy 2.1.2  – requires a visible address bar that displays a secure connection to users when they enter financial information or complete a transaction (see policy definitions).

The reason for this rule is because you are bringing the user to a site that is using HTTPS and the user may be entering in secure information. You need to give the user confidence that you are not spoofing the website and stealing the entered information.

This is easily remedied by adding a TextBlock (which is read-only) to the page and displaying the web address every time a page loads. Conveniently, the WebView has a perfect event handler for this: OnNavigationStarting.

You can get the web address through the Uri property of the WebViewNavigationStartingEventArgs and then set it to the Text property of your TextBlock. This is better explain with some example code.

Let’s say you have a page with a webview, you want to add a TextBlock to the top. You’ll want to create a Grid with two rows, set the first row’s height to Height=”Auto”. Put the TextBlock in Row 0 and the WebView in Row 1.

Now, let’s hook into NavigationStarting of the WebView, and in the event handler grab the Uri and set it to your TextBlock.Text property.

Here is what you should have (put some placeholder text so you can see what it looks like, also use gray for a foreground text color so the user knows it is read-only).

<Grid Background="White">
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto"/>
                <RowDefinition/>
            </Grid.RowDefinitions>
            <TextBlock x:Name="MyAddressBarTextBlock" 
                           Text="http://www.somewebsite.com" 
                           Foreground="Gray" />
            <WebView x:Name="MyWebView" 
                     NavigationStarting="MyWebView_OnNavigationStarting"
                     Grid.Row="1"/>
</Grid>

…and here is what your event handler should look like:

private void MyWebView_OnNavigationStarting(WebView sender, WebViewNavigationStartingEventArgs args)
{
     try
     {
        //the event args contain the web address, get it from args.Uri and hold it in a local variable
        string websiteAddress = args.Uri.ToString();

        //now set the address to the Textblock's text property
        MyAddressBarTextBlock.Text = websiteAddress;
      }
      catch (Exception ex)
      {
         //do something with the error
      }
}

That’s all there is to it! Every time the WebView is going to load a page, the NavigationStarted event will fire and your TextBlock will show the upcoming address.

Here are some screenshots from the my sample…

WinAddressBar2 WinAddressBar

PhoneWebAddressBar2 PhoneWebAddressBar

Happy Coding!
Lance

Extra Credit and Sample Universal App:
This example is barebones, I challenge you to make a user control that houses the WebView and TextBlock, then you can reuse it across your app instead of doing this on every page. I’ve written a demo Universal app for you that has the following:

  • UserControl in the Shared folder (ReadOnlyWebView.xaml)
  • ProgressRing for loading content
  • Extends Source DependencyProperty and exposes Refresh method
  • Instantiates the custom control in MainPage.xaml for both Phone and Windows projects

This should wet your appetite and show you how to extend it further.

DOWNLOAD THE SAMPLE UNIVERSAL APPLICATION

Invalid XAML error updating from WP7

We are now seeing the beginning of the fast decline of Windows Phone 7 as it exits the market over the next several months, many of you will need to act to update your app to at least Windows Phone 8.  I did this for all of my WP7 apps and there was one error that was In just about every upgrade:

An error on this XAML namespace declaration:

xmlns:controls="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls"

Previous to Windows Phone 8, the Pivot and Panorama controls were part of a toolkit. The Windows Phone team did a solid by included these in the OS, they also added new controls like the LongListSelector to replace the toolkit’s ListPicker . These controls are now found in the Phone namespace.

It’s a very frustrating problem if you’re seeing it for the first time. Don’t worry, there is a really easy fix… Delete the xmlns:controls line and use only the xmlns:phone one or edit it and remove the “.Contols” part of the assembly pointer. Here is what it will look like after doing the edit option:

xmlns:controls="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"

However, in many newer app templates, this is already used for the xmlns:phone declaration that looks like this:


xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"

If you do have the xmlns:phone declaraiton, simply delete the bad line xmlns:controls line and change any UI controls on the page to use the phone one instead. For example

Change:

<controls:Pivot x:Name="MyPivot"> foo </controls:Pivot>

to

<phone:Pivot x:Name="MyPivot"> foo </phone:Pivot>

I hope this blog post was found when you searched for the error and it fixed it for you 🙂 Let me know if this doesn’t fix it for you and I’ll take a look at your XAML.

Happy coding!

App Studio – Design-Time Sample Data

If you’re like me, you like to fiddle and tweak things to get just the right result. Recently, Microsoft has really beefed up App Studio apps and if you explore the downloaded source code you’ll see a new Universal app structure leveraging MVVM. Let’s start with the before and after photo (click any image to view larger):

The image on the left is the UI before changes and the one on the right is afterwards
Before and after changes to the items lists

Here is a screenshot of the App Studio solution structure in the Visual Studio Solution Explorer (since AppStudio.Data is a Portable Class Library, you’ll need Visual Studio 2013 Pro [Update 2] or higher. See Tim’s answer for a workaround):

Blog1

So, you’ve got yourself an App Studio app and want to make custom changes, this can be challenging because you won’t see anything in the designer because the data is not generated until runtime.  You’ll have to make educated guesses by using margins of the UI elements.  We can make this much easier this by creating design-time sample data.

This blog post is a tutorial on how to do just that. Keep in mind that even though I have the YouTube schema through out the app, it should work the same regardless of your app’s structure. Let’s get started…

Step One – Download and open the source code in Visual Studio 2013

You can find the source code’s download link on the same page you downloaded the publish package. By default, it is collapsed, just expand the “Source Code” section and click the “Download 8.1 Source Code” link. It is a zipped folder, unblock and then extract it. Once the app is open in Visual Studio 2013, Build (F6) the solution so that the nuget packages are retrieved and added.

Step Two – Generate Sample Data

Now let’s open the project in Blend for Visual Studio (Pro Tip: right-click on AppStudio.WindowsPhone/Views/MainPage.xaml and select “Open in Blend“) so that we can generate sample data for MainViewModel.

  • 0 – Prerequisite: See my blog post here and review Step 3
  • 1 – Open MainPage.xaml located inside AppStudio.WindowsPhone/Views in Blend. Note: Click “Cancel” when Blend asks if you want to set a Resource Dictionary for design-time. (FYI – these steps are the same for AppStudio.Windows project, which you can do after completing this Windows Phone tutorial).
  • 2 – Now create sample data for MainViewModel (Step 3 in my tutorial will show you how to do this) and “Save All” when it’s done.
  • 3 – While the Data tab still open, click the “Set design-time DataContext” link at the bottom, make sure “MainViewModelSampleData.xaml” is highlighted and then click OK. See the screenshot below. ( Alternatively, you can simply add this line to the top of your MainPage.xaml with the xmlns declarations: d:DataContext=”{d:DesignData /SampleData/MainViewModelSampleData.xaml}” )
Click to enlarge
Set Design-Time DataContext

Blog3

Now your MainPage’s design-time DataContext is set to the sample data. Next, we’ll edit the sample data with some image paths so that you can see an images in the designer.

Step Three – Images

One downside to automatically generated sample data is that sometimes you want a path to an image instead of Lorem Ipsum. This is very easy fix that makes life much easier in the designer because Image controls bound to that sample data’s property will show an image, here are the steps:

  • 1 – Add an image to your project (note: I created a “PlaylistIcon160.png” image and added it to the project’s Assets folder).
  • 2 – Open the sample data file, MainViewModelSampleData.xaml (you’ll find it under AppStudio.WindowsPhone/SampleData/, also you’ll want to change your tool window to the XAML-only view because you cannot edit sample data with the designer-only window ).
  • 3 – Find the places in your sample data that are for image paths and replace the lorem text with the image path. For example in my sample data, I have the YouTube schema, which has a property named “ImageUrl” in the Items list, I changed the sample text to the placeholder image’s path. Here is a screenshot of where you’ll find the ImageUrl property and my edit to it:

Blog4

  • 4 – I did this for every ImageUrl property in each of my project’s models in the sample data. This is the most lengthy process of getting the sample data ready, but it’s really worth it to have images visible.
  • 5 – Once all items have been edited, do a Build (F6).

Step Four – Setting d:DataContext

Now we need to set the design data context of your view items to point to the sample data. We already did this at the page level in step two, but we’ll need to set it for each HubItem to display the lists. Here are the steps:

  • 1 – Go back to MainPage.xaml and go to a split view (XAML and designer visible).
  • 2 – Scroll down until you see the <Hub> control. You’ll see a number of “HubSections”. Here is what you should see now:

Blog5

Now, add a d:DataContext=”{Binding ModelNameHere}” to each HubSection. You will find the names in the MainViewModelSampleData tree. In my demo, there are 5 HubSections, each has it’s own model. (App Studio models are outside the scope of this article, but you can read more here on the App Studio website).

This screenshot explains it more clearly:

Blog6

That’s it! You should now be seeing your images and sample data in the designer.

Step 5 – Editing DataTemplates

This is the same process as you do for editing any Template. I wanted to quickly cover it to round out this tutorial. I wanted to get rid of the extra space between items in the list because I don’t have the summary text. Here is what I did:

  • 1 – In the Objects And Timeline pane, expand the Hub control and right click on a HubSection
  • 2 – Select “Edit HubSection“. The Objects and Timeline focus will shift to the DataTemplate of that hub section.

Now let’s edit the ItemTemplate of the ListView that shows the list items:

  1. Right click on ListView
  2. Expand “Edit Additional Templates
  3. Expand “Edit Generated Items (Item Template)
  4. Select “Edit Current

You can now edit the template, I removed the second Grid.Row declaration because it wasn’t being used. I got back 60 pixels on unneeded padding, but remember empty space is just as important as content. So, I added a 12 px margin to the bottom of the Image control. This now allows more items to appear on the smaller phone form factor.

Conclusion

With a little sample data and some independent flavoring, you can customize your App Studio app to give it a truly unique feel. You can see the results of having design-time data right now, here is the app I used in this demo, enjoy!

Here is the Windows Phone version of the customized app

Here is the Windows version of the customized app

Now, go forth and design away!