Overview: Reactive Client-Side Programming

Applies to: Functional Programming

Authors: Tomas Petricek and Jon Skeet

Referenced Image

Get this book in Print, PDF, ePub and Kindle at manning.com. Use code “MSDN37b” to save 37%.

Summary: This article reviews techniques for developing Silverlight applications in F#. It introduces the options for handling user interface events and implementing asynchronous communication.

This topic contains the following sections.

  • Introducing Silverlight Programming
  • Creating Silverlight User Interfaces
  • Handling Events and Communication
  • Summary
  • See Also

This article is associated with Real World Functional Programming: With Examples in F# and C# by Tomas Petricek with Jon Skeet from Manning Publications (ISBN 9781933988924, copyright Manning Publications 2009, all rights reserved). No part of these chapters may be reproduced, stored in a retrieval system, or transmitted in any form or by any means—electronic, electrostatic, mechanical, photocopying, recording, or otherwise—without the prior written permission of the publisher, except in the case of brief quotations embodied in critical articles or reviews.

Introducing Silverlight Programming

The programming model used for developing user interfaces is quite different from that of the applications that do not interact with the user. An application with no user interaction can assume that it’s in the driver's seat—that it controls what happens at each step. On the other hand, a Silverlight application needs to handle a variety of UI events and it often also needs to communicate with a service running on the server side. The execution of this type of application is controlled by the occurrences of events, and the application is concerned with reacting to them. This kind of applications is called event driven. The fact that the application doesn't control the execution is also sometimes called inversion of control (which is a bit confusing because the term has a different meaning in the object-oriented design).

Note

Silverlight is a platform for creating rich internet applications (RIAs) based on the .NET Framework. Silverlight can be used for developing cross-platform applications using the usual .NET ecosystem (tools and languages) because Silverlight applications run on Windows, Mac, Linux, and Windows Phone.

User interface libraries in Silverlight are based on Windows Presentation Foundation (WPF), which is a full-featured user-interface toolkit for desktop applications. Many of the principles in this chapter apply to WPF or even other user-interface frameworks such as Windows Forms.

This article looks at how to program Silverlight user interfaces in F#. The discussed applications run in a web browser, but Silverlight applications are not limited to browser applications. They can work in several ways:

  • Rich Internet Applications (RIA) running in a web browser as part of a web page

  • Standalone applications originating from the Internet but installed locally and running outside of the web browser context

  • Applications running on Windows Phone 7

The article discusses several topics that are directly related to Silverlight. Many of them also apply to Windows Presentation Foundation (WPF). These include, for example, various aspects of working with XAML files. The article also discusses several general user-interface concepts, such as working with events, so it is useful regardless of a specific technology.

Creating Silverlight User Interfaces

The standard Microsoft Visual Studio 2010 installation includes only an F# Silverlight Library template, which creates an assembly that can be referenced from a C# or VB.NET Silverlight project. When using this option, the user interface can be implemented in the C# project. This is easy, but it makes the architecture more complex. An alternative is to explore additional F# templates and create an entire application (including XAML-based user interface) in F#.

Exploring Online Templates

Visual Studio is not limited to using the preinstalled templates. It is possible to install additional templates and there is also an online Visual Studio Gallery that contains numerous additional templates provided by the community. The articles in this section use one such template.

The dialog for creating new projects provides access to the Visual Studio Gallery using the Online Templates option in the left panel. This option provides access to a growing set of additional project templates, including several F# templates. After installing a template, it will appear in the list of installed templates, as demonstrated in Figure 1.

Figure 1. A newly installed template for F# Silverlight applications

Referenced Image

The template in Figure 1 creates a basic F# Silverlight application. The application consists of just two F# source files that define the application with a "Hello World!" text block created from the F# code. The following links give more information about the template:

Designing the User Interface in XAML

Although the Visual Studio templates for F# don't have the same support for developing Silverlight applications as C#, it is possible to use the usual tools, including XAML and Microsoft® Expression Blend. This section gives a brief overview of how a typical F# Silverlight project works and then provides links to more detailed information.

Assume that a project contains a XAML file named Hello.xaml with the usual XAML declarations and the following button:

<Button Content="Click me!" x:Name="MyButton" />

The user interaction of a Silverlight component can be implemented in an F# source file that contains an F# class. The class inherits from the UserControl type (in the System.Windows.Controls namespace) and usually looks something like:

type Sample() as this =
    inherit UserControl()
    let loc = "/ProjectName;component/Hello.xaml"
    do Application.LoadComponent(this, Uri(loc, UriKind.Relative))

The constructor specifies that the Silverlight runtime should load the user interface from the Hello.xaml file that is stored in the resources of the project. After initializing the user interface, it is possible to use the F# dynamic operator (?) to find elements inside the current control. For instance, the code can access the sample button using the following snippet:

let btn : Button = this?MyButton

In contrast with C#, the F# templates in Visual Studio don't generate fields for all named XAML elements automatically, but the dynamic operator provides a simple alternative. The following two articles give more information about using XAML files and implementing the dynamic operator:

Handling Events and Communication

One major reason for choosing F# when developing a Silverlight application is that F# makes it easier to implement asynchronous communication with the server and to handle user interface events. The two features of F# that are invaluable for these purposes are first-class events and asynchronous workflows.

Using First-Class Events

User interaction is typically implemented with code that handles events. In F#, events appear as values of the IEvent<'T> type. As with other ways of exposing events, the type provides ways for registering and unregistering handlers. The unusual aspect is that values of this type can be passed as arguments to functions. This is the idea of being first class. Events can be used in the same way as any other values.

The main benefit of having first-class events is that an F# library can include functions that perform common operations on events. For example, assume there is a displayMessage function that takes a string and displays it in the user interface. Then one can write the following event handling code:

btn.Click |> Observable.map (fun _ -> "Hello world!")
          |> Observable.add displayMessage

This snippet takes the Click event and passes it to the Observable.map operation. The operation builds a new event that is triggered whenever the user clicks on the button. Each time the new event is triggered, it will carry a "Hello world!" message. The next operation in the processing pipeline specifies what should be done when the event occurs. In the snippet above, the text of the event is passed to the displayMessage function.

The example above is very simple but it demonstrates that using functions from the Observable module can make code very concise. A more realistic example can be found in the following tutorial:

Using Asynchronous Workflows

To make sure that applications do not hang while communicating over the network, the Silverlight library provides only asynchronous versions of most methods. This means that the caller needs to specify a callback (or a handler) that will be invoked when the operation completes. However, writing code explicitly using callbacks is quite difficult.

In F#, the task is largely simplified by asynchronous workflows. When a piece of code is wrapped inside an async { … } block, the F# compiler automatically translates it into a version that uses callbacks. The following example defines a workflow that reads the content of a web page specified by serverUri and displays the content in the user interface:

let update = async {
    let wc = new WebClient()
    let! message = wc.AsyncDownloadString(serverUri)
    label.Text <- message }

When downloading the web page (on the third line), the snippet uses the let! construct. This is because the AsyncDownloadString method returns a primitive asynchronous workflow that can be executed without blocking the current thread.

Asynchronous workflows can be used for developing both server-side and client-side components. On the client side, the workflow is usually configured to run on the main user interface thread (so that it can access user interface controls). When using asynchronous workflows for reactive programming, it is possible to use Async.AwaitEvent to wait for user interface events such as mouse clicks. This makes it easy to write long-running computations that involve interaction with the user. More information about this approach can be found in the following tutorial:

Summary

This article briefly reviewed several techniques and features of F# that are useful when developing interactive applications in Silverlight. Although F# doesn't have the same level of integration as C#, it is an attractive choice for user interface programming. New Silverlight F# projects can be created using a rich set of online templates and the user interface can be designed using XAML and Microsoft® Expression Blend.

One reason for using F# for Silverlight development is that it supports asynchronous workflows and first-class events. Asynchronous workflows largely simplify the implementation of communication with the server and the encoding of complex interactions with the user (such as wizards). First-class events give a concise way for implementing common event-processing patterns.

See Also

This article is based on Real World Functional Programming: With Examples in F# and C#. Book chapters related to the content of this article are:

  • Chapter 9: “Turning values into F# object types with members” explains how to use object-oriented features of the F# language. This is an important topic for client-side development because it explains how to mix the object-oriented Silverlight design with the functional programming style.

  • Book Chapter 13: “Asynchronous and data-driven programming” explains how asynchronous workflows work and uses them to download data from the Internet.

  • Book Chapter 16: “Developing reactive functional programs” discusses how to write reactive user interfaces using asynchronous workflows and events. It also includes a basic introduction to the Reactive Framework (Rx).

To download the code snippets shown in this article, go to https://code.msdn.microsoft.com/Chapter-3-Reactive-Client-8a458f7d

Previous article: How to: Create an Agent for Batch Processing

Next article: Tutorial: Creating a Silverlight Project in F# Using the Online Templates