win8dev

How to create an Extended Splashscreen for Universal Apps

Recently, I started to create a real world app to demonstrate the usage of my WordPressUniversal library. While I was working on it, I also decided to extend the Splahscreen which is mandatory for universal apps.There are several reasons to extend the splash screen, the most obvious is to hide initial data loading.

The only sample I found had a separate solution for the Windows and the Windows Phone application, and I decided to put them together to use the advantages of the Shared project that comes with every universal app.

The first step is to add your Splashscreen images to both projects. To do so, open their Package.appxmanifest files and go to the ‘Visual Assets’ tab. Add your images:

Screenshot (371)

Now add a UserControl to your shared project and rename the control type to “Grid” in the XAML file. After that, let us design the UI that is shown to the user when he starts our app:

<Grid.RowDefinitions>
    <RowDefinition/>
    <RowDefinition Height="180"/>
</Grid.RowDefinitions>

<!--Windows needs a Canvas-->
<Canvas x:Name="Win_Splash_Img" 
        Grid.Row="0" 
        Grid.RowSpan="2" 
        Visibility="Collapsed">
    <Image x:Name="extendedSplashImage_Win" 
           Source="Assets/SplashScreen.png"/>
</Canvas>

<!--Windows Phone needs a Viewbox-->
<Viewbox 
    x:Name="WP_Splash_Img"
    Grid.Row="0" Grid.RowSpan="2" 
    Visibility="Collapsed">
    <Image x:Name="extendedSplashImage_WP" 
           Source="Assets/SplashWindowsPhone.png"/>
</Viewbox>

<!--this StackPanel holds our ProgressRing that is telling the user we are doing some work-->
<StackPanel 
    Grid.Row="1" 
    HorizontalAlignment="Center">
    <ProgressRing x:Name="progressRing" 
                  IsActive="True" Margin="0,0,0,12" 
                  Foreground="White" 
                  Background="Black">            
    </ProgressRing>
    <TextBlock x:Name="progressText" 
               Style="{StaticResource TitleTextBlockStyle}" 
               TextAlignment="Center" 
               HorizontalAlignment="Center">
 </TextBlock>
</StackPanel>

This XAML code is the base for our extended Splashscreen. It defines a row height of 180 to place the StackPanel that holds the ProgressRing at the bottom of our control. The main difference here is that Windows Apps use a Canvas while Windows Phone uses Viewbox to hold our Splashscreen Image. We need to set the Visibility on both to collapsed as our code decides which one will be displayed on Launch.

In our code page, we have a bit more work to do. Let’s go through it step by step:

Make sure you have added the following Namespaces:

using Windows.ApplicationModel.Activation;
using Windows.UI.Core;
using ExtendedSplash.Common;

Note: if you do not have a Common folder in your Shared Project, you can add it manually and copy the classes from the demo project attached to this project. Don’t forget to change the Namespaces of the classes to your project name after you added them.

The next step is to declare some objects that we need for the extended Splashscreen:

internal Rect splashImageRect; 
internal bool dismissed = false; 
internal Frame rootFrame;
private SplashScreen splash;

The Rect is used to place the Splashscreen Image in it and will be sized by our code which we will add later. The dismissed bool is used to determine when the system Splashscreen gets dismissed. The rootFrame is used for the navigation to our first application page, while the splash is used to read the needed values for placing our image into the Rect.

After we have declared those objects, we need to overload the main class of our control:

public ExtendedSplash(SplashScreen splashcreen, bool loadstate)

The splashcreen tells us the coordinates and the height of the splash image. You can use the loadstate bool to determine data that needs to be restored by the SuspensionManager, if needed.

As users are snapping our apps or rotating the device, we need to handle this. To do so, we need to add the following line to our constructor:

Window.Current.SizeChanged += new WindowSizeChangedEventHandler(ExtendedSplash_OnResize);

Add this code to handle the resizing:

if (splash != null)
{
    splashImageRect = splash.ImageLocation;
    PositionImage();
}

If the user causes the WindowSizeChanged event to fire, the splash will be loaded again and submits new coordinates to our splash object. To properly handle the positioning, we are using the PositionImage() method:

        void PositionImage()
        {
#if WINDOWS_PHONE_APP
            extendedSplashImage_WP.SetValue(Viewbox.HeightProperty, splashImageRect.Height);
            extendedSplashImage_WP.SetValue(Viewbox.WidthProperty, splashImageRect.Width);
#else
            extendedSplashImage_Win.SetValue(Canvas.LeftProperty, splashImageRect.X);
            extendedSplashImage_Win.SetValue(Canvas.TopProperty, splashImageRect.Y);
            extendedSplashImage_Win.Height = splashImageRect.Height;
            extendedSplashImage_Win.Width = splashImageRect.Width;
#endif
        }

As you can see, we use the preprocessor directive WINDOWS_PHONE_APP to declare the height and width of the Viewbox. If it is not running on Windows Phone, we are setting the canvas coordinates and size via this method. This is not the only point where we need this method, as you will see later in this post.

Let’s go back to our constructor and add this line to load the system’s Splashscreen values into our object:

splash = splashcreen;

Now that we have these values, we are finally able to receive the coordinates and declare which Splashscreen will be used:

            if (splash != null)
            {
                //handle the dismissing of the system's splash 
                splash.Dismissed += new TypedEventHandler<SplashScreen, Object>(DismissedEventHandler);

                //get the system's splashscreen values
                splashImageRect = splash.ImageLocation;

                //decide which control is used to display the splashscreen image and size the progressRing
#if WINDOWS_PHONE_APP
                Win_Splash_Img.Visibility = Visibility.Collapsed;
                WP_Splash_Img.Visibility = Visibility.Visible;
                progressRing.Height = 50;
                progressRing.Width = 50;

#else
                Win_Splash_Img.Visibility = Visibility.Visible;
                WP_Splash_Img.Visibility = Visibility.Collapsed;
                progressRing.Height = 70;
                progressRing.Width = 70;
#endif
                //position and size the image properly
                PositionImage();

            }

 

Let me explain what I have done here. First we need to check if our splash object has a value. Then, we need to handle the Dismissing of the system’s Splashscreen with this TypedEventHandler:

private void DismissedEventHandler(SplashScreen sender, object args)
{
    dismissed = true;
}

After that, I am declaring when to show Windows Phone’s Viewbox and Windows’ Canvas as well as setting the size of the ProgressRing. The last step is to position and size the image again with our PositionImage() method. This will cause the app to switch to our extended Splashscreen.

Now we have to declare a new Frame instance and begin to load our data:

// this frame acts as navigation context
rootFrame = new Frame();
//start loading your data:
LoadData();

For this demo, I used a delay to keep the ProgressRing spinning:

async void LoadData()
{
    progressText.Text = "sleeping, please wait until I wake up...";
    //using a delay to keep the progress ring spinning for this demo
    await Task.Delay(TimeSpan.FromSeconds(5));
    //Navigate to the first application page after all work is done
    rootFrame.Navigate(typeof(MainPage));
    Window.Current.Content = rootFrame;
}

That’s all of the code we need inside our ExtendSplash control. If you now build the project, it will compile, but nothing will happen. other than going directly to the MainPage.

We need to add some additional code to our App.xaml.cs in the OnLaunched event:

//only show the splash if the app wasn't running before
if (e.PreviousExecutionState != ApplicationExecutionState.Running)
{
    //check the loadstate if necessary
    bool loadState = (e.PreviousExecutionState == ApplicationExecutionState.Terminated);
    //create a new instance of our ExtendedSplash
    ExtendedSplash extendedSplash = new ExtendedSplash(e.SplashScreen, loadState);
    //declare our extendedSplash as root content
    rootFrame.Content = extendedSplash;
}

If you hit the debug button, you should have similar results to these:

Screenshot (374)

Screenshot (375)

For your convenience, I created a small demo project. Download it here.

As always, I hope this blog post is helpful for some of you. If you have questions or feedback, feel free to leave a comment below.

Posted by msicc in Archive, 8 comments

A year in the like of MSicc – my review of 2013

dev smurf

2013 was a year with a lot of surprises. It was a year full of community work for me as well as a huge learning year in development. But my year had also dark clouds on heaven. This post is my personal review of 2013 – you can like my impressions or not.

I started the year with releasing my first Windows 8 app ever, along with an huge update to my blog reader app for Windows Phone. I wrote several blog posts and started also development of my NFC Toolkit app for Windows Phone (Archive: January). I also ran a beta test for my NFC Toolkit, and finished my series about the parts that should help other developers  to write a blog reader app for both Windows and Windows Phone (Archive February & Archive March).

Then in April, the first time I had dark clouds hanging deeply in my life, affecting all parts – family, community work and also my 9to5 job. My wife had once again problems with her back, caused by slipped discs. It went as far as she needed to rest in hospital for a pain therapy. Luckily this therapy was helping her and our life went back to normality (knocking on wood).

I also started a new series on the WinPhanDev blog – Why we started developing (WWSDEV). We are collecting stories from developers, and posting them over there to motivate other developers and keep the community spirit alive. Just have a look, we have really great stories over there.

In the last days of April/beginning of May, Iljia engaged me to start using Windows Azure Mobile Services to make an app idea reality: TweeCoMinder was born. It is a very special and unique app, interesting for those that don’t want to miss their special counts on Twitter, supported by real push notifications via WAMS for both Live Tiles and Toast Notifications. I learned a lot during setting up my WAMS for the app, and I did also write some blog posts about that (AzureDev posts).

Because of TweeCoMinder, I stopped developing my NFC app for that time, and did only bug fixing updates to my other apps.

In August (at least in the spare time I had), I moved my blog completely to run in a Windows Azure VM. I did it to get more control over the whole system and to learn more about running a web service. I still need to write my blog posts about setting the VM with LAMP on Azure, but I just didn’t have time for that until now. In August/September I also had again very very dark clouds hanging around, with my wife was very ill (you can’t even imagine how happy I am about the fact she has this part behind her). But our daily live is still affected by this – we just learned to arrange us with the new situation.

In October, I got back to my NFC Toolkit to finish it finally. The app has some cool and unique features utilizing NFC tags, and I am quite satisfied with my download numbers. NFC Toolkit is my main project for the moment.

But also on my 9to5 job I came to write code. I was asked to write an internal app for Windows Phone (Telefónica has a partnership with Microsoft, and so the company is flooded with Windows Phones). I used this to learn more about speech recognition on Windows Phone, as this is part of the application (Make your app listening to the user’s voice).

And finally, I also started with my very first Android app using Xamarin while porting the Windows Phone app I wrote before. I recently started to blog about my experiences with Xamarin (read more here).

In between all those projects, I made a basic reader app for the fan blog “This is Nokia”, using a PCL project for both Windows Phone 8 and Windows 8. I also wrote a simple car dashboard app to integrate it in my NFC Toolkit app as well as Mix, Play & Share, which was written on a lonely Saturday night while my kids where sleeping an my wife was at her best friend.

Through the year, I learned a lot of coding, but also a lot about people. I made some very positive experiences – but also bad ones. I am always willing to help (if my still growing knowledge enables me to do so) – but sharing a feature rich app to another person isn’t helping – if you want to learn about development, there are plenty ways to do so. We have really great developers that blog about their experiences in our community, and by understanding how to code, you truly learn. Just using an already working app and restyling it, is the wrong way.

Well, that is what my year was about – a lot of coding, learning and again coding.

Dear followers, friends, WinPhans & WinPhanDevs – thank you for being with me this year. Let’s make 2014 an even more exciting year.

I wish you all “a good slide into the new year”, as we say here in Germany. May god bless you and your families also in the new year.

Posted by msicc in Editorials, 0 comments

Merry Xmas, everyone!

 

Merry-Christmas

 

This year was an amazing year. We got a lot of new devices, great apps, and a lot of development work was done.

Now, with Xmas around the corner, I want to wish all of you a

Merry Christmas!

After the xmas days, I will start a new series here on my blog, together with my review post of 2013.

Enjoy your family time, and may god bless you all!

Posted by msicc in Archive, 0 comments

How to update a live tile in a background task with web data on Windows 8.1

scheduledtaskWindows

Like I wrote in my last post, I recently finished a PCL project with a Windows Phone and a Windows 8.1 app. Like the Windows Phone version, also the Windows 8.1 app has a live tile that fetches the same data from WordPress.

Taking advantage of our PCL solution structure, we are able to reuse the JSON data class from our PCL.

However, there are a few things that differ from the Windows Phone background agent.

First, we need to add a new project to our solution. In the new project dialog, select ‘Windows Runtime Component’ in the C# Windows Store section.

To make it a background task, implement the interface IBackgroundTask to the generated class in our Runtime component. In order to make it doing some work, we are going to add the ‘Run’-method that will start our background agent.

Here we are already with the first difference. The Windows Runtime does not support direct async Tasks of type string (I fetch all articles via HttpClient in an async task that returns the JSON string). That’s why we need to wrap it in an IAsyncOperation. To do this, add a new sealed class to your Windows Runtime background agent project.

Here is how the code for the IAyncOperation:

        public IAsyncOperation<string> GetLastPostJsonString(string url)
        {
            try
            {
                return AsyncInfo.Run((System.Threading.CancellationToken ct) => GetInternal(url));
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.ToString());
            }
            return null;
        }

        private static async Task<string> GetInternal(string url)
        {
            try
            {
                HttpClient getJsonStringClient = new HttpClient();
                getJsonStringClient.DefaultRequestHeaders.IfModifiedSince = DateTime.Now;

                var response = await getJsonStringClient.GetAsync(url);
                var JsonString = await response.Content.ReadAsStringAsync();
                return JsonString;
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.ToString());
            }
            return null;
        }

Let me explain the code. The IAsyncOperation starts and returns the string of our async Task<string>.  To achieve this, we need to start another async Run that delegates our Task<string> result to the main background task. Unlike a direct HttpClient call, we are not able to save the string directly to an string object. Instead, we need to read the stream.

I highly recommend to wrap this all in try/catch blocks to prevent any crashes of your app.

Let’s go back to our main background task class. Now we are able to fetch the JSON string from web service, we finally can start to implement the Run() method that will actually update our live tiles:

       public async void Run(IBackgroundTaskInstance taskInstance)
       {
           try
           {
               BackgroundTaskDeferral deferral = taskInstance.GetDeferral();

               PostfetcherForTileUpdate fetchJsonString = new PostfetcherForTileUpdate();

               Constants.latestPostsForLiveTileFromWordPressDotComResultString = await fetchJsonString.GetLastPostJsonString(Constants.GetLatestPostsForLiveTileFromWordPressDotComUriString);

               );

               UpdateTile();

               deferral.Complete();
           }
           catch (Exception ex)
           {
               Debug.WriteLine(ex.ToString());
           }
       }

The Run method needs to implement the Interface for IBackgroundTaskInstance. To inform the OS that our background agent may do work after the Run has returned data, we need to use the GetDeferral() method. If we would do that, it may happen that the task will be closed before all action has taken place.

After getting the JSON String from the IAsyncOperation, we can now write it to an object, call our UpdateTile() method and tell the system that our deferral is completed.

Within the UpdateTile() method, we are going to deserialize the JSON String and update our live tile. There are a lot of considerations for the live tiles in Windows 8 and 8.1, make sure you have read the guidelines for tiles and badges on MSDN. Make also sure you check the tile template catalogue to choose the right templates for your app.

Let’s have a look at the UpdateTile() code:

        private static void UpdateTile()
        {
            try
            {
                //create a new Tile updater and allow it to be added to the notification queue
                var updater = TileUpdateManager.CreateTileUpdaterForApplication();
                updater.EnableNotificationQueue(true);
                updater.Clear();

        //deserialize the JSON string
                var LatestPostFromWordpress = JsonConvert.DeserializeObject<json_data_class_Posts.Posts>(Constants.latestPostsForLiveTileFromWordPressDotComResultString);

        //fill in the Tile Templates
                foreach (var item in LatestPostFromWordpress.posts)
                {
            //supporting both Medium and Wide tiles
                    XmlDocument WidetileXML = TileUpdateManager.GetTemplateContent(TileTemplateType.TileWide310x150PeekImage04);
                    XmlDocument SquareTileXML = TileUpdateManager.GetTemplateContent(TileTemplateType.TileSquare150x150PeekImageAndText04);

            //setting the text on our tiles
                    var title = item.title;
                    WidetileXML.GetElementsByTagName("text")[0].InnerText = title;
                    SquareTileXML.GetElementsByTagName("text")[0].InnerText = title;

            //providing the remote image source 
            //if not empty:
                    if (item.featured_image != string.Empty)
                    {
                        XmlNodeList tileImageAttributes = SquareTileXML.GetElementsByTagName("image");
                        ((XmlElement)tileImageAttributes[0]).SetAttribute("src", item.featured_image);
                        ((XmlElement)tileImageAttributes[0]).SetAttribute("alt", "no image");

                        XmlNodeList tileWideImageAttributes = WidetileXML.GetElementsByTagName("image");
                        ((XmlElement)tileWideImageAttributes[0]).SetAttribute("src", item.featured_image);
                        ((XmlElement)tileWideImageAttributes[0]).SetAttribute("alt", "no image");
                    }
            //if empty:
                    else if (item.featured_image == string.Empty)
                    {
                        XmlNodeList tileImageAttributes = WidetileXML.GetElementsByTagName("image");
            //this image has to be in the main Windows 8.1 project, not in the background task!
                        ((XmlElement)tileImageAttributes[0]).SetAttribute("src", "ms-appx:///Images/NoImgPlaceholderMedium.png");
                        ((XmlElement)tileImageAttributes[0]).SetAttribute("alt", "no image");

                        XmlNodeList tileWideImageAttributes = WidetileXML.GetElementsByTagName("image");
            //this image has to be in the main Windows 8.1 project, not in the background task!
                        ((XmlElement)tileWideImageAttributes[0]).SetAttribute("src", "ms-appx:///Images/NoImgPlaceholderWide.png");
                        ((XmlElement)tileWideImageAttributes[0]).SetAttribute("alt", "no image");
                    }

            //perform the update of our live tiles
                    updater.Update(new TileNotification(WidetileXML));
                    updater.Update(new TileNotification(SquareTileXML));
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.ToString());
            }
        }

To make the background task updating our tile, we need to use the TileUpdateManager class. As we are updating our main tile, we are using the CreateTileUpdaterForApplication() method. To make sure our tile is able to queue our update request, we are setting the EnableNotificationQueue property to true.

After deserializing the JSON string, we fill the Template by using DOM methods. I used the GetElementsByTagName(string) method to find the title and the image ChildNodes in the template. This way, I don’t need to care for the Xml structure.

The title content can be set by using the InnerText property. For providing the images source, we need to go through the NodeList, searching for the image NodeChild and use the SetAttribute() method of the XmlElement class.

With the code above, the tile gets a placeholder image, if the JSON string does not return an url for the  featured image. Important: the placeholder image has to be in your main Windows 8 project, not in the background task project. Make also sure that the image(s) have a unique name and do not use the same file name like your base tile image.

That’s all we need to do in our background task project.

Let’s have a look at our main app project. First, we have to declare our background task to make our app registering for the periodic notifications. Open the Package.appxmanifest of your app and navigate to the ‘Declarations’ tab.

Screenshot (259)

Under ‘Available Declarations’, select ‘Background Tasks’ and ‘Add’.

Screenshot (259)

 

Under ‘Description’ check the ‘Timer’ Option. Make sure you referenced your background task project and add it as ‘Entry Point’.

That’s all that wee need to set up in the first step. Now we are going to write our method to register the background task:

        //needs to be async because of the BackgroundExecutionManager
        public async void RegisterBackgroundTask()
        {
            try
            {
        // calling the BackgroundExecutionManager
        //this performs the message prompt to the user that allows the update of our tiles and the permissions entry
                var backgroundAccessStatus = await BackgroundExecutionManager.RequestAccessAsync();

        //checking if we have access to set up our live tile
        if (backgroundAccessStatus == BackgroundAccessStatus.AllowedMayUseActiveRealTimeConnectivity ||
                    backgroundAccessStatus == BackgroundAccessStatus.AllowedWithAlwaysOnRealTimeConnectivity)
                {
            //unregistering our old task, if there is one                   
            foreach (var task in BackgroundTaskRegistration.AllTasks)
                    {
                        if (task.Value.Name == taskName)
                        {
                            task.Value.Unregister(true);
                        }
                    }

            //building up our new task and registering it
                    BackgroundTaskBuilder taskBuilder = new BackgroundTaskBuilder();
                    taskBuilder.Name = taskName;
                    taskBuilder.TaskEntryPoint = taskEntryPoint;
                    taskBuilder.SetTrigger(new TimeTrigger(60, false));
                    var registration = taskBuilder.Register();
                }
            }
        //catching all exceptions that can happen
            catch (Exception ex)
            {
        //async method used, but wil be marked by VS to be executed synchronously
                var message = new MessageDialog("we were not able to activate the live tile. Please restart the application to try again.");
                message.Title = "Sorry,";
                message.ShowAsync();

            }

        }

We are calling the BackgroundExecutionManager of Windows 8.1. This adds the Permissions dialog on the app’s first run as well as the entry in the settings charm. Only if we are allowed by the user, our tile will be updated.

Unregistering already running tasks and re-adding them is a common practice, which I did also here.

After that, I build up a new background task with the BackgroundTaskBuilder class, referencing to the taskEntryPoint I set up in the Declarations tab before.

Unlike the Windows Phone background agent, we can change the time of the background task. I used 60 minutes for this app. You will need to specify a trigger (minimum of 15 minutes). I tried it without, which lead to an exception.

I am catching all exceptions and display a message to the user here. The method will be marked as executing synchronously, but it will work. The reason is that no async methods are allowed in the catch block.

Like always, I added this to my App.xaml.cs file, as this is set up application wide. To start the task, I just call it in the Application.Launched event. It would also work in the OnWindowCreated event, if you want your Launched event free.

Setting up a background task to update your live tile with data from web is not as easy as on Windows Phone, but with this article you will be able to get started on that.

As always, I hope that this post is helpful for some of you.

Happy coding, everyone!

Posted by msicc in Archive, 1 comment

New Series: Getting productive with Windows Azure Mobile Services (WAMS)

WAMS

Now that my current app project is near to go live, I will start a new series about how to get productive with Windows Azure Mobile Services (WAMS).

I will cover some interesting topics in this series, which are not really documented in the very well written “Getting started” series from the Azure team itself.

These topics are (list is subject to be updated if needed):

First, if you want to get  started, you should check out this link: http://www.windowsazure.com/en-us/develop/mobile/tutorials/get-started-wp8/

The tutorial makes you very easy and fast using WAMS.

What can you expect from this series? As always, I will add some of my personal experiences during my journey of creating my app. There were a lot of small stones in my way, and I will also tell you how to remove them. And of course I hope that my posts will help some of you to get their own WAMS story started.

Happy coding everyone!

Posted by msicc in Azure, Dev Stories, 0 comments

Dev Story Series (Part 5 of many): Styling a WebView or WebBrowser element

This post is about styling our WebView or WebBrowser in our app. Until now, we only got the HTML string that we are displaying in our WebView or WebBrowser. It looks like this:

image.png

The content we receive from our WordPress post content includes already all kind of HTML tags like paragraphs, lists, links, images. That is the advantage for this solution: no parsing is needed, the string can be displayed as is. Both the WebView and the WebBrowser framework element (no, they are not controls) are able to read and render CSS code. And this is how we can match the whole element for our app.

HTML Pages can be styled by using a so called cascading style sheet (CSS), which is similar to XAML code. With a little bit of searching on the web you will be able to style “translate” your XAML properties into CSS.

Here is a sample CSS String:

<STYLE type="text/css">
body{background:#034786; width:450px; }
p{font-family:'Segoe UI';color: white;font-size:medium;}
h1{font-family:'Segoe UI';color: white;}
h2{font-family:'Segoe UI';color: white;}
h3{font-family:'Segoe UI';color: white;}
h4{font-family:'Segoe UI';color: white;}
pre{background-color: #C0C0C0; width:100%;}
blockquote{font-family:'Segoe UI';font-style:italic;}
a:link{font-family: 'Segoe UI';color: #C0C0C0; font-size: medium; text-decoration:underline}
li{font-family: 'Segoe UI';color: white;font-size: medium;list-style-type: square;}
img {text-align:center; width:100%: height:100%;}
</STYLE>";

Every CSS string has to be surrounded with “<STYLE type=”text/css”> </STYLE> “. Between those two Style tags, you can set different properties for each kind of HMTL tag:

  • body = the whole page is embedded in the body. this is where we set the background of our content as well as the width and the height
  • p = paragraphs. paragraphs can contain text as well as images or other multimedia content. Mainly used for text like in our blog post, we style how the user is able to read our blog post.
  • h1 – h4 = different kinds of headers. you can define four styles of headers
  • pre = is for lines of code
  • blockquote = if we quote people or other sites, we use quotes to clarify this aren’t our words. should be styled a bit differently than the rest of our blog (e.g. Italic)
  • a:link = how hyperlinks will be styled
  • li = this is how our list will be styled in this view
  • img = how we want to see our pictures in our post

Hint for using CSS in code behind:

If you just C&P the CSS string from above, it will result in some errors from Visual Studio. Visual Studio does not like the new lines in strings, so you have to add it as one line. Also is it not possible to use ‘”‘ within a string declaration. It has to be “escaped”, which we are doing with a simple before it: ‘”‘. I mentioned it because I learned it the very hard way by trying to solve it for 2 hours.

Only thing we now need to do is pass the CSS String together with our HTML string from our JSON to our WebView or WebBrowser element:

WebBrowser.NavigateToString(CSSString + ContentString);

After navigating to this both strings, our content is now displayed like native:

  styledNativeWebView

One last tip:

I recommend to set the Visibility of your WebBrowser or WebView to “Collapsed” until the whole rendering has done. Once the “navigation” has finished, set it via code to visible. This way the user does not recognize that we are rendering the post content for him. Just display a loading animation until that is done. Both elements have a “LoadCompleted” event. Once the rendering (= the navigation to our string) is done, the content of our blog post is shown as it would be natively in our app.

As always, I hope this is helpful for some of you and feel free to leave a comment below.

Posted by msicc in Archive, 0 comments

Dev Story Series (Part 4 of many): How to open links from a WebBrowser/WebView in Internet Explorer

XAMLWebView

Today I will share my solution of how to open links from a WebBrowser or WebView on Windows Phone and Windows 8 (as I did in my app for msicc.net).

Generally links are opened within the same WebBrowser or WebView element. On Windows Phone you can solve this problem pretty easy with only one simple method:

public void WebBrowser_Navigating(object sender, NavigatingEventArgs e)
        {
            e.Cancel = true;
            WebBrowserTask wbt = new WebBrowserTask();
            wbt.Uri = e.Uri;
            wbt.Show();
        }

In Windows 8 this gets a bit more complex. There is no Navigating method, and this is why we have to combine different languages together. We will use the ScriptNotify event to pass the link via a small java script and launch IE with the new link.

First, you need to add the function to your HTML string.  I used a RegEx method to add all the pattern that is needed to all links. As I know that a lot of us (especially junior devs like me) have their problems with RegEx, here is my method to add them:

public static string AddScriptToLink(string text)
        {
            const string hrefScript = " onclick="return OnLinkClick('{0}')" ";
            const string pattern = @"href=""(.*?)""";

            var result = text;

            var matches = Regex.Matches(text, pattern);
            var sortedMatches = matches.Cast<Match>().OrderByDescending(x => x.Index);
            foreach (var match in sortedMatches)
            {
                var replacement = string.Format(hrefScript, match.Groups[1].Value);
                result = result.Insert(match.Index, replacement);
            }

            return result;
        }

After you did that, you will be able to use the following script:

<script type='text/javascript'>
	function OnLinkClick(a) 
		{       
         	 window.external.notify(a);       
		 return false;    
		}
</script>

I pass this script together with the HTML string (HTML methods need to be first!) to the WebView. I recommend to save the script as a static string, so you have do insert only the name of the string.

If you add the ScriptNotify Event to your WebView, you will be able to use LaunchUriAsync with the value of e, which is the link.

private async void WebView_ScriptNotify(object sender, NotifyEventArgs e)
        {
            await Windows.System.Launcher.LaunchUriAsync(new Uri(e.Value));
        }

I am not sure if there is a better way to do this, but that is my way. It works like it should and does not hurt the experience of my app.

As always I hope this is helpful for someone out there. If you have any way to improve that, feel free to leave a comment below.

Posted by msicc in Archive, 0 comments

Dev Story Series (Part 3 of many): Why I use a WebBrowser/WebView to display WordPress post content

When it comes to display the post content on a blog reader app, it starts to become a bit challenging. The post content is formatted to look great on your website. But when we pull our posts into an app, there is only the naked, HTML formatted string.

As developer, you have to think about several things now:

  • What part of the content do I want to be displayed?
  • How do I get the images there?
  • What if there is a video in the post?
  • Where do I put the Links in?
  • How can I handle enumerations?
  • and so on…

There is the HTMLAgilityPack out there, but I never got a satisfying result out of it. The next method would be to write a custom parser. This is what I have done before, in the old version of the app for my WordPress blog. It did work, but I had to invest a real big amount of time in it before I got a result that I was able to live with. I was also not too experienced with RegEx (and I am still not) that I could set up a perfect parser.

When I was creating the Windows 8 version of my app, I wanted to achieve a good reading experience. On the other side I  wanted the code to be as reliable as possible, because there are often changes on WordPress that can have impact on my app.

As I mentioned above, the post content is already formatted. It is formatted in HTML.  I decided to render the content string instead of parsing it.

It is pretty easy to do that. Just pass the content string to your desired details page, and use a WebBrowser on Windows Phone or a WebView on Windows 8. Without any parsing, just by “navigating” to the passed string, we will get a result like this:

image

So we have already a readable result, and if my app has only white background, I could leave it like it is and go on.  Without any additional line of code.

Using the WebBrowser/WebView brings also additional advantages:

  • Pinch-to-Zoom support
  • Orientation support
  • automatic image downloading without any additional control
  • WebView on Windows 8 embeds videos automatically

I don’t want to hide that there are a few points that we need to handle, which will be subject of additional posts:

  • styling of content to match our app colors
  • Navigation to links (including a solution for video links on Windows Phone)
  • Scroll direction in Windows 8 WebView

I know it might be not the best practice for displaying web content, but I am really satisfied what I achieved by using the WebBrowser and WebView element in my apps.

I hope the upcoming blog posts will be helpful for some of you to create also a good user experience by using these elements. Of course these posts will contain some code. Before starting the posts about it I just wanted to share why I used these elements.

 

Posted by msicc in Archive, 0 comments

Dev Story Series (Part 2 of many): Getting recent posts from WordPress into your Windows Phone and Windows 8 app

Now that we have a full WordPress JSON class, we are able to download our recent posts from WordPress into our apps for Windows Phone and Windows 8. I am still not using MVVM to keep it simple (and because I have to dive into it more deeply).

The first thing we need to do is to download the JSON string for the recent posts. The Uri scheme is pretty simple: {yourblogadresshere}?json=get_recent_posts

I declared a public string in my MainPage for that, so it is very easy to use it in our app.

The second thing we are going to do is to download the JSON string into the app.

For Windows Phone I used a WebClient, as I want to keep it compatible with the Windows Phone 7 OS. I will update the App with an dedicated WP8 version later, for the moment it is working on both OS versions. Add this code to you Page_Loaded event:

                WebClient GetPostsClient = new WebClient();
                GetPostsClient.Headers[HttpRequestHeader.IfModifiedSince] = DateTime.Now.ToString();
                GetPostsClient.DownloadStringCompleted += new DownloadStringCompletedEventHandler(GetPostsClient_DownloadStringCompleted);
                GetPostsClient.DownloadStringAsync(new Uri(RecentPostJsonUri));

We will also have to add the Handler for GetPostsClient_DownloadStringCompleted:

 void GetPostsClient_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
        {
            App.jsonString_result = e.Result;
        }

In Windows 8 there is no WebClient, so I used an HttpClient:

                        HttpClient getJsonStringClient = new HttpClient();
                        getJsonStringClient.DefaultRequestHeaders.IfModifiedSince = DateTime.UtcNow;
                        App.jsonString_result = await getJsonStringClient.GetStringAsync(RecentPostJsonUri);

Both the Windows Phone and the Windows 8 apps are downloading the string asynchronously, the UI is reliable all the time. You may have noticed the additional Header that I request. This way, we are able to integrate a refresh function into our app. If we leave this out, our app uses the cached string, and users will have to exit the app to refresh the list of our posts.

You will have to declare a public static string variable for the downloaded string in App.xaml.cs, that keeps the downloaded string accessible through the whole app.

Until now we have only downloaded our JSON String, which looks like this:

image

Side note: The WordPress JSON API has a dev mode. Just add “&dev=1” to your above created Uri, and you will be able to see the whole JSON string in a readable form in your browser.

Back to our topic. Off course this is not a good format for users. They want to see only the content, without all the formatting and structuring code around.

What we need to do, is to deserialize our JSON String. This is possible with Windows Phone and Windows 8 own API, but I highly recommend to use the JSON.net library. You can download and learn more about it here. To install the library, just go to Tools>Library Package Manager>Manage NuGet Packages for Solution, search for JSON.net, and install it.

After installing the package, we are able to use only one line of code to deserialize our JSON String to our data members:

var postList = JsonConvert.DeserializeObject<Posts>(App.jsonString_result);

Now we need the deserialized data to be displayed to the user. The desired control for Windows Phone is a ListBox, for Windows 8 you it is called  ListView. We need to create an ItemTemplate in XAML and bind the data we want to show to the user (Just change ListBox to ListView for Windows 8 in XAML):

<ListBox x:Name="PostListBox">
                <ListBox.ItemTemplate>
                    <DataTemplate>
				<StackPanel>
 				<Image x:Name="PostImage" 
				       Source="{Binding thumbnail}" />
                           	<TextBlock x:Name="TitleTextBlock" 
				           Text="{Binding title}" 
					   TextWrapping="Wrap" 
					   FontSize="20" />
                                <TextBlock x:Name="PublishedTextBlock" 
					   Text="{Binding date}" 
					   FontSize="12"/>
				</StackPanel>
                    </DataTemplate>
                </ListBox.ItemTemplate>
          </ListBox>

As you can see, we have set some Bindings in the code above. This Bindings rely on the DataContract Post, as every ListBox/ListView-Item represents one Post of our postList.

[DataContract]
public class Post
    {
        [DataMember]
        public int id { get; set; }
        [DataMember]
        public string type { get; set; }
        [DataMember]
        public string slug { get; set; }
        [DataMember]
        public string url { get; set; }
        [DataMember]
        public string status { get; set; }
        [DataMember]
        public string title { get; set; }
        [DataMember]
        public string title_plain { get; set; }
        [DataMember]
        public string content { get; set; }
        [DataMember]
        public string excerpt { get; set; }
        [DataMember]
        public string date { get; set; }
        [DataMember]
        public string modified { get; set; }
        [DataMember]
        public List<Category> categories { get; set; }
        [DataMember]
        public List<object> tags { get; set; }
        [DataMember]
        public Author author { get; set; }
        [DataMember]
        public List<comment> comments { get; set; }
        [DataMember]
        public List<Attachment> attachments { get; set; }
        [DataMember]
        public int comment_count { get; set; }
        [DataMember]
        public string comment_status { get; set; }
        [DataMember]
        public string thumbnail { get; set; }
    }

Choose the fields you want to display to create your own DataTemplate to show only the data you want. Last but not least we have to tell our app that the ItemSource of our ListBox is the deserialized list, which is also done easily:

PostListBox.ItemsSource = postList.posts;

If you now hit F5 on your keyboard, the app should be built and the device/emulator should show your recent posts in a list. You don’t need to add additional code to download the images, as the image source points already to an image and will be downloaded automatically.

Pro-Tip:

The thumbnails from the our DataContract Post are looking really ugly sometimes. To get a better looking result in your ListBox/ListView, I recommend to use the attached images. To do this, you will need the following code:

          foreach (var item in postList.posts)
            {
                var postImagefromAttachement = item.attachments.FirstOrDefault();
                if (postImagefromAttachement == null)
                {
                    item.thumbnail = placeholderImage; //add your own placeholderimage here
                }
                else
                {
                    item.thumbnail = postImagefromAttachement.images.medium.url;
                }

            }

This code checks your list of attachments in your post, takes the first image, and downloads a higher quality (medium/full).  I am using medium to get best results on quality and download speed.

I hope this is helpful for some of you to get forward for to create a WordPress blog app on Windows Phone and Windows 8.

Happy coding!

Posted by msicc in Archive, 1 comment

Editorial: 2012 – what a year!

logo_white

The year is coming to an end soon, so I wanted to write a short summary of my 2012 with Microsoft and MSicc.net.

Screenshot (47)

I started the year with a clean install of the Windows 8 preview, and was using it since then as my main PC OS. Everyday I felt more in love with the speed of Windows 8 and the idea of using apps on a PC. Microsoft constantly updated their previews over the year, until the final release.

Also Windows Phone was getting new attraction with the awesome Lumia 900. Nokia and Microsoft started a big ad campaign to support the launch of this device. Surely some of you will remember of “The smartphone beta test is over”.

WP_20121225_069

Over the year, Microsoft did tease us a few times with Windows Phone Apollo. We all thought in the beginning that our existing devices will be getting the Apollo treatment, until MS unleashes some more details about Windows Phone 8. Windows Phone 8 shares a lot of the OS with Windows 8, so naturally there has to be new hardware. Windows Phone 7 will get 7.8, which will bring at least the look of the start screen to older devices.

WP_000586

Another beta program was launched for the Xbox Dashboard, which had better voice functionality, and of course another big thing: Internet Explorer on Xbox! That is really awesome as we are now able to surf the web with Kinect support as well as the Smart Glass app on your phone/tablet/PC.

Screenshot (51)

Which leads me to another fantastic release from Microsoft. The Smart Glass apps, no matter on which platform you will use it, extends the experience of films, games and also your Music experience.

Screenshot (48)

Talking about Music, Microsoft finally launched their Music Pass in Germany. Personally, I was waiting for this since the initial release of Windows Phone 7, and now they finally launched it. I did not wait a second to cancel my Spotify subscription, and switched to the Music Pass. And I love the experience, be it on WP7, WP8 or Windows 8/ Xbox, my collection is synched across all devices. I can choose which Songs I ‘ll keep in the cloud for streaming and which I download, so there is always a growing collection for me now.

I was also attending several developer days from Microsoft, which helped me in some parts of my own dev story. I updated Fishing Knots SE and plus several times this year and created I learn to tie my shoes, which is getting really good reviews all over the web. If you want to take a look at these apps, they all come with a test version, just type MSiccDev in the search, you will get a list with all of my apps.

Screenshot (52)

Sadly I have a bit trouble with the updated version of MSicc’s Blog for Windows Phone, I hope I can release it in early 2013, so you all can read and discuss or share articles from your phone.

Of course all of my Windows Phone apps will receive a special Windows Phone 8 update while keeping the work on the WP7 version.

I have also started development of a Windows 8 app for MSicc’s Blog, which I will submit in the early 2013 days to Microsoft to get it approved for the Windows 8 store.

Screenshot (53)

My personal highlight this year was to attend a keynote of Steve Ballmer himself, which was absolutely motivating as user and even more as developer. He really knows how to keep the crowd attending, and I really have to thank Microsoft Germany for this unique experience.

I want to thank Mark and Sean for joining me here on MSicc.net to entertain and inform you all, I bet we will see some awesome articles of both next year!

A big thanks also to the WPDev & Win8Dev community out there (you all know who you are). Keep up your great work and please keep the community alive!

Now I will come to an end with this post, as I want to further play around with my awesome Lumia 920 which Santa (aka my lovely wife) gifted me this year at Xmas.

What were your highlights this year? Leave a comment below!

As here in Germany is said for the new year wishes in advance: “Have a good slide into the new year”, stay safe and enjoy your time!

Posted by msicc in Editorials, 5 comments