Windows 8 and HTML Part 4: First Taste of WinJS

8/14/2012 12:56:58 PM

Continuing with Part 4 of building WinRT applications with HTML and JavaScript.  You can find earlier installments at their respective links: Part 1Part 2Part 3If you are interested in the source code for the TweetScan application, you can get it off of GitHub.

Watch the Part 4 video

Let’s switch back to a WinJS application and take a look at what happens when a page is loaded.  Open package.appxmanifest and switch the Start Page back to default.html.

If you remember from Part 1, we created this application as a single-page style application.  This means that default.html gets loaded once, and different pieces of HTML content are then loaded “into” default.html for rendering and execution.  If we look at default.html, we see two important things.

Capture7First, we see that default.html loads the core script files for the WinJS framework and then the default.js script file (where we put our code), and also navigator.js, which helps navigate from page to page (with page really being HTML content being loaded into default.html).  The second thing to notice is that default.html contains a single div that is marked as a PageControlNavigator control.  It is this div that serves as the content host for the rest of the content.

Take a look at default.js.  It is comprised of a self-calling function that sets up the WinJS infrastructure.  The first three lines are the heart of getting the WinJS Application up and running.

    var app = WinJS.Application;
    var activation = Windows.ApplicationModel.Activation;
    var nav = WinJS.Navigation;

First, a WinJS Application namespace is acquired. This Application namespace provides application-level functionality. For right now, we are most interested in the various application-level events that are fired as the application runs.  We will explore Activation and Navigation as we get deeper into the application.

Events

Understanding the order of events in a WinJS application is important.  Knowing when events fire and in what order is critical to determining the best place to put your application  code.  In a single-page application, you have three categories of events available to you: traditional browser events, WinJS application events, and page events.

Browser Events

Traditional browser events are exactly what they sound like.  Since HTML/JS apps in WinRT are actually leveraging the IE10 rendering a JavaScript engines, it makes sense that these events are available.  This means that you can detect and handle events like the Window object’s onload event and the Document object’s DOMContentLoaded event.  This is especially useful when moving an existing, browser-based application to Windows 8.  You would wire these events up inside default.js

Application Events

The new events that are part of the WinJS environment are those provided by the Application and by Pages being loaded for display.  There are three main Application events.  The most common is the activated event, and this is the event that is wired automatically for you in default.js.  In the event handler you will find boilerplate startup code for determining how your application was started (tap on the Start tile = launch, targeted for a Search from the Search Charm = search, etc.), the previous execution state of the application (terminated by the user, suspended by the OS), and a call to WinJS.UI.processAll().  The processAll() call walks the DOM and finds all of the HTML elements that have been marked as WinJS UI controls, like the div marked as a PageControlNavigator we looked at earlier.  Prior to the activated event, the loaded event is fired.  Once the application has been activated, and all other Page events (to be discussed shortly) fire, the Application fires the ready event.

Page Events

When working with a single-page navigation model, each new piece of content or view is constructed as its own Html page (typically).  As these pages are loaded and rendered in the default.html’s PageControlNavigator, the new html page can load additional JavaScript files.  If you look at home.js, you will see the usual implementation for single-page applications.  Home.js makes a call to WinJS.UI.Pages.define(). This function defines the page that is being loaded, and as a result, exposes a series of events that you can hook into.  The default implantation shows only the ready event:

    WinJS.UI.Pages.define("/pages/home/home.html", {
        ready: function (element, options) {
            // TODO: Initialize the page here.
        }
    });

There are two other events you can define in the same way ready is defined: init and processed.  Both of these events occur prior to the ready event.  Init fires before any of the content of the new page has been set.  Processed will fire once the content has been set, but before any remaining processing has been completed.

Event Order

The complete order of all of these events is shown below

  • Default.js self-calling function
  • Application Loaded event
  • Document DOMContentLoaded
  • Application activated event
  • Window loaded event
  • Home.js self-calling function
  • Page init event
  • Page processed event
  • Page ready event
  • Application ready event

The documentation says that Application loaded follows DOMContentLoaded. However, in all of my testing so far, I have always seen DOMContentLoaded follow Application loaded.  I am not sure if the documentation is wrong, or if it is some strange artifact in the debug environment.  As some point, I will get around to logging the events so I can read them without having to be in debug mode.   Just something to keep in the back of your head.

Until next time…

Tags:

Windows 8 | Headlines | Screencasts

Message Based Navigation for WP7 MVVM Apps

4/26/2011 8:30:00 AM

Do you have an MVVM-based Windows Phone 7 application and you don't like having to hook into the RootFrame to navigate between pages? Do you wish you could just "ask" to navigate to a new view from your view model? One possible solution can be found in my new Channel 9 screencast.

Using an message bus to process navigation messages, view models can publish messages that are then handled by a separate navigation service, successfully decoupling your view model from the Windows Phone navigation service.

Get the finished source code here

Tags:

Blend | Windows Phone | Screencasts | MVVM

Simple Dependency Injection with XAML

1/17/2011 5:01:25 PM

Update: Channel 9 video in case you don’t want to read the article.

Download demo code here

Let’s start by painting a simple scenario:  I have a ViewModel that lists a collection of data items.  Let’s say a list of Tweets based on a given hash tag search.  The ViewModel has a SaveCommand that I will wire into my view.  When the user causes the SaveCommand to execute, the ViewModel will leverage some service to persist the selected tweet to some form of storage.  And there is the rub…  Maybe in v1, I will save that tweet in IsolatedStorage, but in the future, I will want to also provide an option to select a cloud-based storage solution.  This is is where we start to hear all kind of things about Dependency Injection, IoC, and more. 

Hey, I am a fan of Dependency Injection and using in IoC container, but the what I hate about DI/IoC is that is takes me away from the pure XAML-based goodness of defining my ViewModel in XAML view an element’s DataContext and into the world of code-behind and setting things up with code. I would much rather do this in MainPage.xaml

<UserControl.DataContext>
     <nScreenLibrary_ViewModels:SearchViewModel/>
</UserControl.DataContext>

than have to start resorting to this in my MainPage.xaml.cs code-behind file…

this.DataContext = new SearchViewModel();
Obviously this is a simple example that does not use DI or an IoC.  Things would be much more complicated as I would need to configure the IoC, call into the IoC to get the correct instance of a ViewModel, and then assign that to my DataContext. I would really like to be able to stick to a XAML-based solution for configuring my application to use different storage providers without having to resort to using code-behind, picking an IoC, etc.  While the DI/IoC route may be needed for complex scenarios, a lot of applications only need a simple solution.

That brings us to using XAML to accomplish a version of Property-based Dependency Injection.  By no means am I saying this solution is perfect.  But I think it will work for a lot of people.  There really is no rocket science here, but if you are still new to XAML and haven’t explored a lot of its power, this may prove a useful solution.  In addition, as I searched around the Intertubes for a similar approach, I couldn’t find one which means I am either blazing a trail that will prove beneficial to many, or I am so far off the reservation that the Developer Police will be coming to take me away shortly.

That brings us to the solution.  Suppose I have a ViewModel that looks something like this

    public class SearchViewModel :BaseViewModel
    {
        public ObservableCollection<MyDataItem> SearchItems{ get; set; }
        public ICommand SaveCommand { get; set; }
        private IFavoritesService _favs;
        public SearchViewModel() : base()
        {
            this.Tweets = new ObservableCollection<Tweet>();      
        
            this.SaveCommand = new RelayCommand()
            {
                CanExecuteCommand = (tweet) => { 
                    var saveTweet = tweet as Tweet; 
                    return saveTweet != null;
                },
                ExecuteCommand = (tweet) => {
                    var saveTweet = tweet as Tweet;
                    if (saveTweet != null)
                        _favs.Save(CurrentSearchTag, saveTweet);
                }
            };
        }
    }

As you can see from the code, the SearchViewModel will use some implementation of IFavoritesService in the SaveCommand’s ExecuteCommand property.  Let’s say that I have a concrete implementation of that service that would look something like this…

public class IsolatedStorageFavs : IFavoritesService
{
    public void Save(string searchTag, Models.Tweet tweet) {
          // do some saving
    }
}

How do I get the IsolatedStorageFavs object into the SearchViewModel without using some kind of DI/IoC and code-behind solution?  The answer is surprisingly simple.

First, let’s update our SearchViewModel implementation by adding a FavoritesStorage property as shown below

public class SearchViewModel : BaseViewModel
{
     private IFavoritesService _favs;
     public IFavoritesStorageService FavoritesStorage {
          get { return _favs; }
          set { _favs = value; }
     }
}

You could simple replace the private _favs member with an automatic property as well… it’s up to you but I wanted to show how to modify the existing example.  With that change, we can now modify our XAML as shown below:

<UserControl.DataContext>
     <nScreenLibrary_ViewModels:SearchViewModel>
         <nScreenLibrary_ViewModels:SearchViewModel.FavoritesStorage>
             <nScreenLibrary_Services:IsolatedStorageFavs/>
         </nScreenLibrary_ViewModels:SearchViewModel.FavoritesStorage>
     </nScreenLibrary_ViewModels:SearchViewModel>
</UserControl.DataContext>

Now, when the application is run, an instance of IsolatedStorageFavs will be created automatically and assigned to the SearchViewModel’s FavoritesStorage property.  If at a later date I wanted to swap in a cloud-based storage solution, I could just go back to my MainPage.xaml file and replace the XAML with the correct markup to instantiate a CloudStorageFavs, for example.

The one drawback is that  you are limited to Property-based Dependency Injection.  If you need access to the property during construction of your ViewModel, this will not work since Silverlight/WPF will not assign the property an object until after construction is complete.  Another one, though not a big deal IMHO, is that if you are not comfortable working with XAML, adding namespaces, etc. then you may want to stick to doing this kind of thing in code.  I feel, however, that this is much simpler thing to learn than diving into DI/IoC if you have not done that before.

Tags:

Silverlight | XAML | Screencasts

Windows Phone 7 April CTP and TransitioningContentControl

5/20/2010 1:50:00 PM

In my original screencast (read here or on Channel 9), I showed you how to use the Silverlight Toolkit’s TransitioningContentControl to add automatic transitions between pages of your Windows Phone 7 Silverlight application.  A few days after recording and posting that screencast, Microsoft released an updated version of the tools and the emulator.  Soon after, I started to get reports from folks watching my screencast that the TransitioningContentControl not only didn’t work with the April CTP release, but it prevented their entire application from running.

Bummer! ;-)  I started to dig into it, and it “appears” that the TransitioningContentControl is suffering from the bug talked about here.  I say it “appears” to be related to that because the symptoms are the same, but unfortunately, the provided fix does not work on the System.Windows.Controls.Layout.Toolkit assembly that is created by building the Silverlight Toolkit.  I think it has something to do with the fact that the System.Windows.Controls.Layout.Toolkit project uses the output of several other projects, which are probably signed as well.  I am not sure how that propagates into the final assembly, but the Powershell script does not fix things.

To solve the problem, I just went “brute force” and added the necessary source files from the TransitioningContentControl project to my own project and called it good.  A better step would have been to break that source out into its own project and create an unsigned assembly containing just the TCC that I could then reuse between Windows Phone projects, but I am assuming at this point that whatever the bug is (signed assembly or other), will be fixed in a future release.  In the interim, this get the job done.

Watch the short video (5 minutes) to see how to get things set up.  Skip to the 2:30 mark if you want to get right to the step required to add TCC directly to your project.

Download source here

Tags:

Screencasts | Windows Phone

Simplifying Page Transitions in Windows Phone 7 Silverlight Applications

4/26/2010 1:33:00 PM

Screencast of this article is available:

Source code of sample application download here.

If you have played around with Silverlight on Windows Phone 7, one thing you may have tried to figure out is how to add nice transitions between different pages of your application.  By default, Windows Phone page transitions really aren’t transitions at all.  The new PhoneNavigationPage is just popped into the root PhoneNavigationFrame.  Effective, yes. Cool, certainly not.  Face it, modern mobile applications need to not only be functional, but also stylish.  Simple “snap” transitions just don’t cut it.

The most common solution to this problem is to use brute force and manage the transitions yourself.  You commonly see a “pattern” used in WP7 apps where events in your current page launch a Storyboard animation.  When that animation is complete, the actual navigation to the new page is invoked and the new page then runs its own Storyboard once it is loaded.  It looks something like this…

// CURRENT PAGE
       private void CurrentPage_Click(object sender, EventArgs e)
       {
           SomeStoryboard.Completed += new EventHandler(SomeStoryboard_Completed);
           SomeStoryboard.Begin();                       
       }

       void SomeStoryboard_Completed(object sender, EventArgs e)
       {
           NavigationService.Navigate(new Uri("/Favorites", UriKind.Relative)); 
       }

// NEWPAGE
protected override void OnNavigatedTo(Microsoft.Phone.Navigation.PhoneNavigationEventArgs e)
{
    base.OnNavigatedTo(e);

    SomeNewStoryboard.Begin();
}

It’s a straightforward solution, and if your app only has a few pages, it works just fine.  If you have lots of pages in your application, however, it becomes quite tedious and hard to maintain.

A better solution can be found by turning to the Silverlight Toolkit.  The great thing about having Silverlight on WP7 is that you can leverage many existing Silverlight assets.  In this case, we will leverage the TransitioningContentControl from the Toolkit.  The TransitioningContentControl was created to solve the same problem we are facing for traditional navigation-based Silverlight application.

To get started, download the Silverlight Toolkit from CodePlex. Once installed, you will need to add the System.Windows.Controls.Layout.Toolkit assembly to your WP7 project.

If you are not familiar with the TransitioningContentControl, its a fairly simple control.  The TCC is comprised of two ContentPresenters – current and previous.  When you update the Content property of the TCC, it will take the content of the CurrentContentPresenter (if present) and move it to the PreviousContentPresenter.  The new content is loaded into the CurrentContentPresenter.  The TCC, however, manages the visibility of the previous and Current ContentPresenters so that the “old” content is visible and the “new” content is hidden.  It then uses a Storyboard that is defined as part of the TCC’s VisualStateManager to transition from the “old” content to the “new” content.  If you are not familiar with Storyboards, the Visual State Manager, or other designer-type topics, have no fear.  The TCC comes with a set of standard transitions that you can use out of the box.

Getting the TCC to work with our WP7 app is a simple process.  First, we need to modify the ControlTemplate for our PhoneNavigationFrame to use the TCC.  By doing so, we automatically enable transitions between any PhoneNavigationPages we add to our app.  To change the PhoneNavigationFrame, open the App.xaml file.  First, add a couple of namespaces to our xaml:

    xmlns:layout="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Layout.Toolkit"
    xmlns:vsm="clr-namespace:System.Windows;assembly=System.Windows"

Now, modify the PhoneNavigationFrame as shown below:

        <phoneNavigation:PhoneApplicationFrame x:Name="RootFrame" Source="/MainPage.xaml">
            <phoneNavigation:PhoneApplicationFrame.Template>
                <ControlTemplate>
                    <layout:TransitioningContentControl Content="{TemplateBinding Content}" Style="{StaticResource TransitioningStyle}"/>
                </ControlTemplate>
            </phoneNavigation:PhoneApplicationFrame.Template>
        </phoneNavigation:PhoneApplicationFrame>

 

The TCC has its Style property set to a StaticResource.  This Style provides the default transitions and is also where you would add your own VisualStates and Storyboards if you would like to add custom transitions.  This Style can be found in the Silverlight Toolkit in the TCC Sample Application, or you can get it from the sample WP7 application linked to this article.  The Style is long so I won’t show the entire thing here, but the first parts of the Style are below to give an idea of what the Style contains and how it is used by the TCC.

  <Style x:Key="TransitioningStyle" TargetType="layout:TransitioningContentControl">
            <Setter Property="Transition" Value="DefaultTransition" />
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="layout:TransitioningContentControl">
                        <Border Background="{TemplateBinding Background}" 
                                BorderBrush="{TemplateBinding BorderBrush}" 
                                BorderThickness="{TemplateBinding BorderThickness}" 
                                CornerRadius="2">
                            <vsm:VisualStateManager.VisualStateGroups>
                                <vsm:VisualStateGroup x:Name="PresentationStates">
                                    <vsm:VisualState x:Name="DefaultTransition">
                                        <Storyboard>
                                            <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" 
                                                                           Storyboard.TargetName="CurrentContentPresentationSite" 
                                                                           Storyboard.TargetProperty="(UIElement.Opacity)">
                                                <SplineDoubleKeyFrame KeyTime="00:00:00" Value="0" />
                                                <SplineDoubleKeyFrame KeyTime="00:00:02.300" Value="1" />
                                            </DoubleAnimationUsingKeyFrames>
                                            <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" 
                                                                           Storyboard.TargetName="PreviousContentPresentationSite" 
                                                                           Storyboard.TargetProperty="(UIElement.Opacity)">
                                                <SplineDoubleKeyFrame KeyTime="00:00:00" Value="1" />
                                                <SplineDoubleKeyFrame KeyTime="00:00:02.300" Value="0" />
                                            </DoubleAnimationUsingKeyFrames>
                                        </Storyboard>
                                    </vsm:VisualState>
                                    <vsm:VisualState x:Name="Normal">
                                        <Storyboard>
                                            <ObjectAnimationUsingKeyFrames BeginTime="00:00:00" 
                                                                           Storyboard.TargetName="PreviousContentPresentationSite" 
                                                                           Storyboard.TargetProperty="(UIElement.Visibility)">
                                                <DiscreteObjectKeyFrame KeyTime="00:00:00">
                                                    <DiscreteObjectKeyFrame.Value>
                                                        <Visibility>
                                                            Collapsed
                                                        </Visibility>
                                                    </DiscreteObjectKeyFrame.Value>
                                                </DiscreteObjectKeyFrame>
                                            </ObjectAnimationUsingKeyFrames>
                                        </Storyboard>
                                    </vsm:VisualState>

 

I won’t break the Style down in detail, but I’ll point a couple of highlights.  First, the Transition property is set to the VisualState that you would like to use as the transition between pages.  Every transition will use this VisualState storyboard.  The DefaultTransition VisualState is an example of how Storyboards are constructed for use in a transition.  As you can see, each Storyboard must target both the CurrentContentPresentationSite and the PreviousContentPresentationSite (these are the ContentPresenters discussed earlier).  You can target more than one property if you like.  Below is a custom transition that can be found in my sample app that both rotates the projection plane and the opacity of the ContentPresenters.

<vsm:VisualState x:Name="SwingTransition">
                                        <Storyboard>
                                            <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Projection).(PlaneProjection.RotationY)" 
                                                                           Storyboard.TargetName="PreviousContentPresentationSite">
                                                <EasingDoubleKeyFrame KeyTime="0" Value="0"/>
                                                <EasingDoubleKeyFrame KeyTime="0:0:0.7" Value="90"/>
                                            </DoubleAnimationUsingKeyFrames>
                                            <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" 
                                                                           Storyboard.TargetName="PreviousContentPresentationSite">
                                                <EasingDoubleKeyFrame KeyTime="0" Value="1"/>
                                                <EasingDoubleKeyFrame KeyTime="0:0:0.7" Value="0"/>
                                            </DoubleAnimationUsingKeyFrames>
                                            <DoubleAnimation Duration="0" To="0" 
                                                             Storyboard.TargetProperty="(UIElement.Projection).(PlaneProjection.CenterOfRotationX)" 
                                                             Storyboard.TargetName="PreviousContentPresentationSite" />
                                            <DoubleAnimation Duration="0" To="1" 
                                                             Storyboard.TargetProperty="(UIElement.Projection).(PlaneProjection.CenterOfRotationX)" 
                                                             Storyboard.TargetName="CurrentContentPresentationSite" />
                                            <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Projection).(PlaneProjection.RotationY)" 
                                                                           Storyboard.TargetName="CurrentContentPresentationSite">
                                                <EasingDoubleKeyFrame KeyTime="0" Value="90"/>
                                                <EasingDoubleKeyFrame KeyTime="0:0:0.7" Value="0"/>
                                            </DoubleAnimationUsingKeyFrames>
                                            <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" 
                                                                           Storyboard.TargetName="CurrentContentPresentationSite">
                                                <EasingDoubleKeyFrame KeyTime="0" Value="0"/>
                                                <EasingDoubleKeyFrame KeyTime="0:0:0.7" Value="1"/>
                                            </DoubleAnimationUsingKeyFrames>
                                        </Storyboard>
                                    </vsm:VisualState>

 

That’s it.  You now have transitions any time you Navigate to a new PhoneNavigationPage

Tags:

Screencasts | Windows Phone

Building a Composite WPF Application Part 6: Working with Models

4/7/2009 11:36:00 AM

In this installment of the Building a Composite WPF App (Prism) series, I take a look at building models. I show why we may build View specific models and how they will be exposed by the Presenters in the Northwind Business Center application.  I say this in the screencast, but it is very possible to combine the presenter and the model into a single ViewModel, but I have kept them separate for illustration purposes. 

 

Download video here

Download source code here

Tags:

Screencasts | WPF Composite App

Building a Composite WPF Application Part 5: Building a Basic Presenter

4/6/2009 5:02:00 PM

The next installment of the Building Composite WPF app series is now available.  In this installment, I introduce building a simple View implementation in the MVP or MVVM style. The demo illustrates creating simple view that will be used to display a list of customers in our Northwind Business Center application.

 

Download video here

Download source code here

Tags:

Screencasts | WPF Composite App

Building a Composite WPF Application Part 4: Intro to Views

4/6/2009 4:16:00 PM

The next installment of the Building Composite WPF app series is now available.  In this installment, I introduce building a simple View implementation in the MVP or MVVM style. The demo illustrates creating simple view that will be used to display a list of customers in our Northwind Business Center application.

 

Download video here

Download source code here

Tags:

Screencasts | WPF Composite App

Building a Composite WPF Application Part 3: Intro to Modules

1/23/2009 8:05:00 PM

The next installment of the Building Composite WPF app series is now available.  In this installment, I introduce Modules by providing an overview of what they are and an example of the steps involved in creating one.  The demo illustrates a simple view from a Module being displayed in our Northwind Business Center application.

 

Download video here

Download source code here

Tags:

Screencasts | WPF Composite App

Developer Minute has a Heart Beat

8/22/2008 8:27:19 AM

Yep, I have finally been able to shave a little time and start working on Developer Minute.  Still in alpha stage right now, but I've made some decent progress on the Silverlight part (mostly by stealing code from here and there), but getting closer.  Besides the intro video playing, not much else is out there.  No RSS yet, I need an Episode data template to clean up the UI stuff, I want some pop-up functionality, and right now all the data is coming from Spaghetti Code screencasts (I will be putting they same functionality into my SlickThought to watch screencasts as well).  I've had some challenges getting WCF to work with my hoster so instead of dealing with some of those hassles I am changing the way I server up the RSS. 

Stay tuned...

Tags:

Screencasts | Slick Thoughts | SpaghettiCode

Powered by BlogEngine.NET 1.6.0.0
Theme by Mads Kristensen

About the author

Jeff Brand Jeff Brand

This is the personal web site of Jeff Brand, self-proclaimed .NET Sex Symbol and All-Around Good guy. Content from my presentations, blog, and links to other useful .NET information can all be found here.

E-mail me Send mail


Calendar

<<  July 2014  >>
MoTuWeThFrSaSu
30123456
78910111213
14151617181920
21222324252627
28293031123
45678910

View posts in large calendar

My Twitter Updates

XBOX
Live

Recent comments

Disclaimer

The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.

© Copyright 2014

Sign in