fiGure 16-4
The F# Application template simply creates an F# project with a single source file, Program.fs,
which is empty except for a reference to the F# Developer Center, http://fsharp.net. If you want
to learn more about F# a great place to start is the F# Tutorial template. This creates a normal F#
project except for the main source file, Tutorial.fs, which contains approximately 280 lines of
documentation on how to get started with F#. Walking down this file and checking out what language
features are available is an interesting exercise in itself. For now, return to the Program.fs and
quickly get the canonical “Hello World” example up and running to see the various options available
for compilation and interactivity. Add the following code:
#light
printfn "Hello, F# World!"
The first statement, #light, is a compile flag to indicate that the code is written using the optional
lightweight syntax. With this syntax, whitespace indentation becomes significant, reducing the need
for certain tokens such as in and ;;. The second statement simply prints out “ Hello, F# World! ”
to the console.
If you have worked with previous versions of F# you may fi nd that your code now
throws compiler errors. F# was born out of a research project and it has only now
been converted into a commercial offering. As such, there has been a refactoring
of the language and some operations have been moved out of FSharp.Core into
supporting assemblies. For example, the print_endline command has been
moved into the FSharp.PowerPack.dll assembly. The F# Powerpack is available
for download via the F# Developer Center at http://fsharp.net.
f# .
329
You can run an F# program in two ways. The first is to simply run the application as you would
normally (press F5 to start debugging). This compiles and runs your program as shown in Figure 16-5.
fiGure 16-5
The other way to run an F# program is to use the F# Interactive window from within Visual Studio.
This allows you to highlight and execute code from within Visual Studio, and immediately see
the result in your running program. It also
allows you to modify your running program
on the fly!
The F# Interactive window is available from
the View . Other Windows . F# Interactive
menu item, or by pressing the Ctrl+Alt+F key
combination, as shown in Figure 16-6.
In the Interactive window, you can start
interacting with the F# compiler through
the REPL (Read Eval Print Loop) prompt.
This means that for every line of F# you
type, it will compile and execute that line
immediately. REPLs are great if you want
to test ideas quickly and modify programs
on the fly. They allow for quick algorithm
experimentation and rapid prototyping.
However, from the REPL prompt in the
F# Interactive window, you essentially
miss out on the value that Visual Studio
delivers through IntelliSense, code snippets,
and so on. The best experience is that of
both worlds: using the Visual Studio text
editor to create your programs, and piping
that output through to the Interactive
Prompt. You can do this by hitting Alt+Enter on any
highlighted piece of F# source code. Alternatively,
you can use the right-click context menu to send
a selection to the Interative window, as shown in
Figure 16-7.
Pressing Alt+Enter, or selecting Send To Interactive,
pipes the highlighted source code straight to the
Interactive Prompt and executes it immediately, as
shown in Figure 16-8.
fiGure 16-6
fiGure 16-7
fiGure 16-8
330 .
chaPter 16 lAnguAge-SpeciFic FeATureS
Figure 16-8 also shows the right-click context menu for the F# Interactive window where you can
either Cancel Evaluation (for long running operations) or Reset Session (where any prior state will
be discarded).
exploring f# language features
A primer on the F# language is beyond the scope of this book, but it’s worth exploring some of the
cooler language features that it supports. If anything, it should whet your appetite for F#, and act as
a catalyst to learn more about this great language.
A very common data type in the F# world is the list. It’s a simple collection type with expressive
operators. You can define empty lists, multi-dimensional lists, and your classic flat list. The F# list
is immutable, meaning you can’t modify it once it’s created; you can only take a copy. F# exposes a
feature called List Comprehensions to make creating, manipulating, and comprehending lists easier
and more expressive. Consider the following:
#light
let countInFives = [ for x in 1 .. 20 do if x % 5 = 0 then yield x ]
printf "%A" countInFives
System.Console.ReadLine()
The expression in braces does a classic “for” loop over a list that contains elements 1 through 20
(the “..” expression is shorthand for creating a new list with elements 1 through 20 in it). The “do”
is a comprehension that the “for” loop executes for each element in the list. In this case, the action
to execute is to “yield” x where the if condition “when x module 5 equals 0” is true. The braces are
shorthand for “create a new list with all returned elements in it.” And there you have it — a very
expressive way of defining a new list on the fly in one line.
F#’s Pattern Matching feature is a flexible and powerful way to create control flow. In the C# world,
we have the switch (or simply a bunch of nested “if else’s”), but we’re usually constrained to the type
of what we’re switching over. F#’s pattern matching is similar, but more flexible, allowing the test
to be over whatever types or values you specify. For example, take a look at defining a Fibonacci
function in F# using pattern matching:
let rec fibonacci x =
match x with
| 0 | 1 -> x
| _ -> fibonacci (x - 1) + fibonacci (x - 2)
printfn "fibonacci 15 = %i" (fibonacci 15)
The pipe operator (|) specifies that you want to match the input to the function against an
expression on the right side of the pipe. The first says return the input of the function x when x
matches either 0 or 1. The second line says return the recursive result of a call to Fibonacci with an
input of x – 1, adding that to another recursive call where the input is x – 2. The last line writes
the result of the Fibonacci function to the console.
Pattern matching in functions has an interesting side effect — it makes dispatch and control flow over
different receiving parameter types much easier and cleaner. In the C#/VB.NET world, you would
summary .
331
traditionally write a series of overloads based on parameter types, but in F# this is unnecessary,
because the pattern matching syntax allows you to achieve the same thing within a single function.
Lazy evaluation is another neat language feature common to functional languages that F# also
exposes. It simply means that the compiler can schedule the evaluation of a function or an expression
only when it’s needed, rather than precomputing it up front. This means that you only have to run
code you absolutely have to — fewer cycles spent executing and less working set means more speed.
Typically, when you have an expression assigned to a variable, that expression gets immediately
executed in order to store the result in the variable. Leveraging the theory that functional
programming has no side effects, there is no need to immediately express this result (because in-
order execution is not necessary), and as a result, you should only execute when the variable result is
actually required. Take a look at a simple case:
let lazyDiv = lazy ( 10 / 2 )
printfn "%A" lazyDiv
First, the lazy keyword is used to express a function or expression that will only be executed when
forced. The second line prints whatever is in lazyDiv to the console. If you execute this example,
what you actually get as the console output is “(unevaluated).” This is because under the hood
the input to printfn is similar to a delegate. You actually need to force, or invoke, the expression
before you’ll get a return result, as in the following example:
let lazyDiv2 = lazy ( 10 / 2 )
let result = lazyDiv2.Force()
print_any result
The lazyDiv2.Force() function forces the execution of the lazyDiv2 expression.
This concept is very powerful when optimizing for application performance. Reducing the amount
of working set, or memory, that an application needs is extremely important in improving both
startup performance and run time performance. Lazy evaluation is also a required concept when
dealing with massive amounts of data. If you need to iterate through terabytes of data stored on
disk, you can easily write a Lazy evaluation wrapper over that data, so that you only slurp up the
data when you actually need it. The Applied Games Group in Microsoft Research has a great
write-up of using F#’s Lazy evaluation feature with exactly that scenario: http://blogs.technet
.com/apg/archive/2006/11/04/dealing-with-terabytes-with-f.aspx.
suMMary
In this chapter you learned about the different styles of programming languages and about their
relative strengths and weaknesses. Visual Studio 2010 brings together the two primary .NET
languages, C# and VB, with the goal of reaching feature parity. The co-evolution of these languages
will help reduce the cost of development teams and projects, allowing developers to more easily switch
between languages. You also learned about the newest addition to the supported Microsoft languages,
Visual F#. As the scale of problems that we seek to solve increases, so does the complexity introduced
by the need to write highly parallel applications. Visual F# can be used to tackle these problems
through the execution of parallel operations without adding to the complexity of an application.
PART IV
rich client applications
. chaPter 17: Windows Form Applications
. chaPter 18: Windows Presentation Foundation (WPF)
. chaPter 19: Office Business Applications
17
Windows forms applications
what’s in this chaPter?
.
Creating a new Windows Forms application
.
Designing the layout of forms and controls using the Visual Studio
designers and control properties
.
Using container controls and control properties to ensure that your
controls automatically resize when the application resizes
Since its earliest days, Visual Studio has excelled at providing a rich visual environment for
rapidly developing Windows applications. From simple drag-and-drop procedures to place
graphical controls onto the form, to setting properties that control advanced layout and
behavior of controls, the designer built into Visual Studio 2010 provides you with immense
power without having to manually create the UI from code.
This chapter walks you through the rich designer support and comprehensive set of
controls that are available for you to maximize your efficiency when creating Windows
Forms applications.
GettinG started
The first thing you need to get started is to create a new Windows Forms project. Select the
File . New . Project menu to create the project in a new solution. If you have an existing
solution to which you want to add a new Windows Forms project, select File . Add .
New Project.
336 .
chaPter 17 WindoWS FormS ApplicATionS
Windows Forms applications can be created with either VB or C#. In both cases, the Windows
Forms Application project template is the default selection when you open the New Project dialog
box and select the Windows category, as shown in Figure 17-1.
fiGure 17-1
The New Project dialog allows you to select the .NET Framework version you are targeting. Unlike
WPF applications, Windows Forms projects have been available since version 1.0 of the .NET
Framework, and will stay in the list of available projects regardless of which version of the
.NET Framework you select. After entering an appropriate name for the project, click OK to create
the new Windows Forms Application project.
the windows forM
When you create a Windows application project, Visual Studio 2010 automatically creates a
single blank form ready for your user interface design (see Figure 17-2). You can modify the visual
design of a Windows Form in two common ways: by using the mouse to change the size or position
of the form or a control or by changing the value of the control’s properties in the Properties
window.
The Windows form .
337
fiGure 17-2
Almost every visual control, including the Windows Form itself,
can be resized using the mouse. Resize grippers appear when the
form or control has focus in the Design view. For a Windows
Form, these are visible only on the bottom, the right side, and
the bottom-right corner. Use the mouse to grab the gripper
and drag it to the size you want. As you are resizing, the dimensions
of the form are displayed on the bottom right of the status bar.
There is a corresponding property for the dimensions and
position of Windows Forms and controls. As you may recall
from Chapter 2, the Properties window, shown on the
right-hand side of Figure 17-2, shows the current value of many
of the attributes of the form. This includes the Size
property,
a compound property made up of the Height and Width. Click
the expand icon to display the individual properties for any
compound properties. You can set the dimensions of the form in
pixels by entering either an individual value in both the Height
and Width properties, or a compound Size value in the format
width, height.
The Properties window, shown in Figure 17-3, displays some of
the available properties for customizing the form’s appearance
and behavior.
fiGure 17-3
338 .
chaPter 17 WindoWS FormS ApplicATionS
Properties are displayed in one of two views: either grouped together in categories or in
alphabetical order. The view is controlled by the first two icons in the toolbar of the Properties
window. The following two icons toggle the attribute list between displaying Properties and