Two more WP7 tutorials

I've just upated the Windows Phone 7 Example Applications list with the next two applications. Both are a little longer, and little more complex as I try to introduce some more features. Given that both also use Expression Blend to do some of the work I've included videos on how to use Blend.

Count Me In is an app to help you keep your place while counting, it introduces the MVVM pattern, commands, binding and behaviors.

Reaction Time tests your reaction speed and brings into play the Silverlight Visual State Manager, transforms and transitions.

Hope you enjoy.

Shout It Kick It submit to reddit

Social Media Html Helpers

I'm currently in the process of writing the next to tutorials in my Windows Phone 7 tutorial series and thought I'd share these snippets of code.

public static class SocialMediaExtensions

{

    public static HtmlString DotNetShoutOut(this HtmlHelper htmlHelper, string url)

    {

        url = HttpUtility.UrlEncode(ToAbsolute(htmlHelper.ViewContext.HttpContext.Request, url));

 

        var img = new TagBuilder("img");

 

        img.Attributes["src"] = "http://dotnetshoutout.com/image.axd?url=" + url;

        img.Attributes["alt"] = "Shout It";

        img.Attributes["style"] = "border: 0px;";

        img.Attributes["width"] = "82";

        img.Attributes["height"] = "18";

 

        var a = new TagBuilder("a");

 

        a.Attributes["rev"] = "vote-for";

        a.Attributes["href"] = "http://dotnetshoutout.com/submit?url=" + url;

 

        a.InnerHtml = img.ToString(TagRenderMode.SelfClosing);

 

        return new HtmlString(a.ToString(TagRenderMode.Normal));

    }

 

    public static HtmlString DotNetKicks(this HtmlHelper htmlHelper, string url)

    {

        url = HttpUtility.UrlEncode(ToAbsolute(htmlHelper.ViewContext.HttpContext.Request, url));

 

        var img = new TagBuilder("img");

 

        img.Attributes["src"] = "http://dotnetkicks.com/services/images/kickitimagegenerator.ashx?url=" + url;

        img.Attributes["alt"] = "Kick It";

        img.Attributes["style"] = "border: 0px;";

        img.Attributes["width"] = "82";

        img.Attributes["height"] = "18";

 

        var a = new TagBuilder("a");

 

        a.Attributes["rev"] = "vote-for";

        a.Attributes["href"] = "http://dotnetkicks.com/kick/?url=" + url;

 

        a.InnerHtml = img.ToString(TagRenderMode.SelfClosing);

 

        return new HtmlString(a.ToString(TagRenderMode.Normal));

    }

 

    public static HtmlString Reddit(this HtmlHelper htmlHelper, string url)

    {

        url = HttpUtility.UrlEncode(ToAbsolute(htmlHelper.ViewContext.HttpContext.Request, url));

 

        var img = new TagBuilder("img");

 

        img.Attributes["src"] = "http://reddit.com/static/spreddit7.gif";

        img.Attributes["alt"] = "submit to reddit";

        img.Attributes["style"] = "border: 0px;";

 

        var a = new TagBuilder("a");

 

        a.Attributes["rev"] = "vote-for";

        a.Attributes["href"] = "http://reddit.com/r/programming/submit?url=" + url;

 

        a.InnerHtml = img.ToString(TagRenderMode.SelfClosing);

 

        return new HtmlString(a.ToString(TagRenderMode.Normal));

    }

 

    private static string ToAbsolute(HttpRequestBase request, string url)

    {

        if(request == null)

            throw new ArgumentNullException("request");

 

        if(url == null)

            throw new ArgumentNullException("url");

 

        var format = request.IsSecureConnection ? "https://{0}{1}" : "http://{0}{1}";

 

        return String.Format(format, request.Url.Host, url);

    }

They're pretty simple little helpers and can be used for any urls. The only thing that may need to change is the ToAbsolute method which is only for the root application. To the use the helpers in my blog I have the following.

<p>

    <%: Html.DotNetShoutOut(Url.Action("Posts", new { slug = Model.Slug.ToLower() })) %>

    <%: Html.DotNetKicks(Url.Action("Posts", new { slug = Model.Slug.ToLower() })) %>

    <%: Html.Reddit(Url.Action("Posts", new { slug = Model.Slug.ToLower() })) %>

</p>

Shout It Kick It submit to reddit

More Windows Phone 7 Tutorials

I've just posted the third and fourth tutorials in my series in recreating the AppsAmuck sample applications for Windows Phone 7. These two cover Tasks and connecting to a JSON service. Both of these show some limitations in the current WP7 SDK.

Tasks

My IP Address

You can view the full list at Windows Phone 7 Tutorials.

Shout It Kick It submit to reddit

Windows Phone 7 Tutorials : Apps Amuck

I always do a lot better with learning new technologies when there's a clear goal in mind, some small application that uses the functionality I want to learn. The AppsAmuck website currently provides 31 of these example applications for people wanting to learn iPhone development, what better way to learn some Windows Phone 7 (and Silverlight) than by working my way through bringing these applications across to WP7.

I' have the first two applications, Minutes to Midnight and Candle already up at Windows Phone 7 Tutorials.

Shout It Kick It submit to reddit

Caliburn 1.1 on Windows Phone 7

I've always enjoyed working with the Caliburn framework for WPF and Silverlight, having the view and view model wired with so many conventions makes creating a rich view model really easy. So one of the first things I did after getting a hold of the Windows Phone 7 CTP was to try and get Caliburn working.

On a side note Rob Eisenberg has released Caliburn Micro which is a slimmed down version of Caliburn that also targets WP7. It's a great little library but has some problems in the WP7 version due to the incomplete binding infrastructure in WP7 (lack of binding on anything not subclassing FrameworkElement), this makes Action Parameters impossible. The original Caliburn doesn't have this problem due to a more complicated code base.

Getting Caliburn 1.1 to compile for WP7 wasn't too difficult, some features like DefaultWindowManager were dropped and since we don't have support for System.Reflection.Emit then some of the code in DelegateFactory didn't work. In the end I replaced with some anonymous methods using simple reflection. Not as elegant and probably not as performant.

As a bonus I've included the Ninject library and Caliburn Ninject adapter.

So how do get this whole thing going? First we have to look at some of the ways the Windows Phone 7 framework expects things to work and how it impacts Caliburn. These also affect Caliburn Micro as well.

The major one is that WP7 expects the RootVisual to be a PhoneApplicationFrame, this provides a lot of the navigation support as well as Orientations. You can circumvent this but from comments from Microsoft you'll be fighting the framework the entire way (for example WP7 will close an application that hasn't navigated within the first ten seconds). If you end up supporting the navigation metaphor essentially you're now using a "view first" approach rather than the default Caliburn approach of "view model first".

public partial class ShellView

{

    private readonly IServiceLocator serviceLocator;

    private readonly IBinder binder;

 

    public ShellView(IServiceLocator serviceLocator, IBinder binder)

    {

        this.serviceLocator = serviceLocator;

        this.binder = binder;

 

        InitializeComponent();

 

        Loaded += OnLoaded;

        Navigated += OnNavigated;

    }

 

    private void OnLoaded(object sender, RoutedEventArgs e)

    {

        // I prefer this to start navigation than the _default Task in WMAppMainfest.xml

        Navigate(new Uri("/Views/MainPageView.xaml", UriKind.Relative));

    }

 

    private void OnNavigated(object sender, NavigationEventArgs e)

    {

        var viewModel = BuildViewModel(e);

 

        binder.Bind(viewModel, e.Content, null);

 

        var presenter = viewModel as IPresenter;

 

        if(presenter == null)

            return;

 

        presenter.Initialize();

        presenter.Activate();

    }

 

    private object BuildViewModel(NavigationEventArgs e)

    {

        var viewType = e.Content.GetType();

 

        var viewModelTypeName = viewType.FullName.Replace("View", "ViewModel");

        var viewModelType = Type.GetType(viewModelTypeName);

 

        return serviceLocator.GetInstance(viewModelType);

    }

}

Unlike Silverlight 4 we can't alter the content loader in PhoneApplicationFrame, so for navigation we'll need to handle when the frame changes it's current page and wire in a view model at this state. We can do this via a "view model locator" in the same faction as the default "view locator", but for the moment we'll manually wire the view and the view model. Caliburn Micro has slightly better support for the "view first" approach and I'll tackle that next. Below is a link containing the assemblies and a sample project.

Download Caliburn 1.1 for Windows Phone 7

Shout It Kick It submit to reddit