Windows-based
user interface programming is based on an architecture that has remained
fundamentally unchanged for more than a quarter century. Since back in
the early 1980s through today, all applications have had the same basic
underpinnings: The main application runs a message loop, picks up
Windows messages off of the message queue, and deposits them into a
window handler. Every window is responsible for rendering its own
presentation—that is, every window, from the top-level window of the
application to the most minor control in the window.
Nearly all Windows-based applications today use the Win32 application programming interface (API) at the lowest level. The classic Win32
API has worked well for a long time. However, its design is beginning
to show its age. Because every window and control is responsible for its
own rendering using the Win32 Graphics
Device Interface (GDI, or the GDI+ interface, in the case of Windows
Forms), fundamental user interface limitations are built into the design of the Windows operating system. The GDI
and GDI+ interfaces have a huge array of functions. However, it takes a
lot of work to do much more than basic drawing and text rendering. That
is, special effects such as transformations, transparency, and video
play integration are difficult to accomplish using the current Windows
graphics interface. Windows does support a richer graphics-based
interface named Direct X; however, using it is often beyond the scope of
most Windows-based applications and is typically reserved for use by
game programmers.
The limitations of the classic Windows API prompted Microsoft to
develop a new programming interface: the Windows Presentation Foundation
(WPF). With WPF, programming special effects for Windows-based
applications (including presenting Web content, as described later) is
very approachable. The WPF libraries are made up of a number of classes
that work together very much like the Windows Forms classes do (on the
surface at least; underneath the goings-on are very different from
Windows Forms).
WPF represents a very rich programming interface for developing a user interface. Here's a short list of the kinds of features available through WPF (this is a broad summary and is not exhaustive):
-
User interface elements that you can modify in all kinds of ways much more easily than you can using Win32 and subclassing
-
Paths, shapes, and geometries for drawing two-dimensional presentations
-
Transforms
(scaling, translating, rotation, and skewing) that allow consistent and
uniform modifications to all user interface elements
-
Ability to manage the opacity of individual elements
-
Built-in layout panels
-
Brushes—image, video, and drawing brushes for filling areas on the screen
-
Animations
WPF applications arrange the UI elements using layout
panels. Rather than relying on absolute positioning (as is the case for
Win32 applications) or flow layout (as is the case for ASP.NET pages),
WPF introduces a number of layout options including the following:
-
Grid Elements are placed in a table.
-
StackPanel Elements are stacked vertically or horizontally.
-
Canvas Elements are positioned absolutely.
-
DockPanel Elements are positioned against the sides of the host.
-
WrapPanel Elements are repositioned to fit when the host is resized.
The example that follows later uses the Canvas.
You craft a typical WPF application from files in very much the same
way that you create an ASP.NET application. A stand-alone WPF
application includes a main application object that runs the message
loop and one or more windows, which are browser-based WPF
applications made up of pages. WPF application components are typically
composed from a markup file, just like ASP.NET pages are. WPF layouts
are defined using Extensible Application Markup Language (XAML).
XAML files describe a WPF layout's logical
tree, the collection of WPF user interface elements. A WPF application
is made up of Common Language Runtime (CLR) classes underneath the
façade of markup language, very much like the ASP.NET object model is.
XAML files represent instructions for constructing a logical
tree of visual elements. In the case of a stand-alone Windows
application, the logical tree exists in a top-level window. In the case
of a browser-based application, the logical tree exists in a browser
pane. The following is a short XAML listing that displays "Hello World"
in a button hosted in a browser pane:
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
<Button Height="100" Width="100">Hello World</Button>
</Page>
The preceding code doesn't do a whole lot, but it is an example of the fundamental structure of a WPF
page as expressed in XAML. When run, the XAML you see listed starts a
browser session and displays a button with the string "Hello World" as
its content (provided the XAML plug-in is installed). In a real
application, instead of containing a single button with a string, the
top-level WPF node can contain elaborate layouts using the different
layout panels available in WPF. You see an example of this soon.
How Does WPF Relate to the Web?
What does all this mean for Web applications? Windows Internet
Explorer and other browsers running under the Windows operating system
are based on the classic Windows architecture. Browsers are responsible
for rendering HTML using the graphic interface available to Windows: the
Graphics Device Interface (GDI).
Consequently, accomplishing special effects in browsers (and typical
HTML) is just as difficult as it is with traditional Windows programs.
Web programming is based on submitting HTTP requests to a server,
processing the requests, and sending back responses to the client. In
that sense, any user interface–specific responses are constrained to
whatever can be expressed in HTML. The Web is dynamic, and HTML is
basically a document technology.
Is there another markup language that provides more than just simple
tags that can be interpreted by an HTML browser? Yes, that's what XAML
is when used in the context of a Web application.
Remember the previous code example? If the contents of the file are
saved in an ASCII text file named HelloWorld.xaml, and you double click
it in Windows Explorer, Internet Explorer loads and parses the XAML
content. Figure 1
shows how it appears in Internet Explorer when you load the XAML file
into the browser. Simply double-click the file name in Windows Explorer
to see the application.
When adding WPF-style content directly to a Web site, you have three options: presenting the content through loose
XAML files, creating an XAML-based browser application (XBAP), or using
Silverlight.
As just shown, if you place a properly formatted XAML file in your
site and make it available through a Web server, any browser capable of
using the XAML plug-in (such as Internet Explorer) can pick it up and
render it. This is one option for presenting WPF-based content from a Web site. This technique is useful for rendering semidynamic content—that is, for rendering anything expressible using pure XAML files.
The WPF programming model marries XAML layout instructions with
accompanying code modules in very much the same way that ASP.NET does.
Events generated from user interface elements are handled in the
accompanying code. Deploying s as loose XAML files precludes adding event handlers and accompanying code.
However, WPF elements are dynamic in the sense that they can be
animated, and user interface elements can be tied together using only
XAML. That's why WPF content expressed only through XAML is semidynamic.
You can hook up some interactive elements using only XAML, but there's a
limit. For example, all through XAML you can render a list of names of
images in a list box and allow users to select an image to zoom. You can
attach slider controls to user interface elements so that the end user
can change various aspects of the elements through the slider. However,
you cannot implement event handlers for controls; that requires
deploying a WPF application as an XBAP application.
XBAPs are another way to deploy WPF content over the Web. They're a bit more complex than loose
XAML files are. In addition to expressing layout, XBAPs support
accompanying executable code for each page. When you deploy a WPF
application over the Web, the client receives the WPF visual layout and
the accompanying code is downloaded to the client computer. Events
occurring in the XBAP are handled on the client side.
The upside of deploying an application as
an XBAP is that it works in very much the same way that a Windows-based
desktop application works (though with greatly reduced permissions and
tightened security). For example, the application can handle mouse click
events and can respond to control events all on the client side.
Although XBAPs are not related directly to ASP.NET, XBAP content can be hosted in ASP.NET-served pages in the same way that loose
XAML content can be served. That is, you can make redirects to XBAP
files or host XBAP files from within <iframe> HTML elements.
Microsoft Visual Studio includes a wizard for generating XBAPs that
can present WPF content. In addition, the user interface elements
contained in the WPF content can respond to events and messages the same
way as any other desktop application can. When browsers surf to your
XBAPs (which are ultimately deployed through Internet Information
Services), they will have a very desktop-like experience in terms of
user interface rendering and responsiveness, even though the application
is running in a browser. The following exercise illustrates how to
create an XBAP.
Creating an XBAP
-
Start Visual Studio and click File, New Project. Go to the Windows application templates and select WPF Browser Application. Name the Application XBAPORama, as shown here:
-
Visual Studio should have created for you a new XBAP that includes a page and an application XAML file set. The file names are Page1.xaml/Page1.xaml.cs and App.xaml/App.xaml.cs.
This is very similar to the ASP.NET Web Form application structure in
that there is a markup file that contains the bulk of the UI and a code
file that implements functionality to be run on the client. Visual
Studio should show the Page1.xaml file, which contains a Grid layout panel.
-
Change the layout panel from a Grid to a StackPanel so that it is simpler to work with. With a StackPanel, you can drop in controls and not worry about creating grid columns and rows:
<Page x:Class="XBAPORama.Page1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300"
Title="Page1">
<StackPanel>
</StackPanel>
</Page>
-
Modify the XAML a bit more. Change the FontSize property for the Page to 16. Nest the following controls in the StackPanel: a TextBox, a ListBox, and a Button. WPF
works very similarly to ASP.NET in that you can name controls in the
markup file (the XAML file) and they will appear as programmatic
elements in the code behind. Set the Name property for the TextBox to "theTextBox" and set the Name property of the ListBox to "theListBox" so that you can refer to them in the code files. Finally, set the Height property of the ListBox to 100 so that it will show up even if it is empty:
<Page x:Class="XBAPORama.Page1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300"
Title="Page1" FontSize="16">
<StackPanel>
<TextBox Name="theTextBox"></TextBox>
<ListBox Name="theListBox" Height="100"></ListBox>
<Button>Click to Add Items</Button>
</StackPanel>
</Page>
The Designer should show all the controls in the StackPanel like this:
-
Double-click the button to add a handler. Visual Studio creates a
handler for the button click. You can find the handler in the code file
for the page. Because you didn't name the Button, Visual Studio gave the handler a default name of Button_Click. The method looks very much like the ASP.NET button click handlers except the second argument is a RoutedEventArg instead of the .NET typical EventArg.
-
Implement the handler by adding whatever is in the TextBox to the ListBox. It should feel almost like you are programming a Web Form—the code model is very similar:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace XBAPORama
{
/// <summary>
/// Interaction logic for Page1.xaml
/// </summary>
public partial class Page1 : Page
{
public Page1()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
this.theListBox.Items.Add(this.theTextBox.Text);
}
}
}
-
Press Ctrl+F5 from within Visual Studio to run the application in the browser. When you type text into the TextBox and click the Button, the code running on the client side will add the contents of the TextBox to the ListBox, as follows (notice the .xbap extension at the end of the file name in the URL):
Although this example does not strictly run
in ASP.NET, it does show an alternative way of producing content. When
you compiled the application, Visual Studio created a few files
including XBAPORama.xbap
and XBAPORama.exe. You can include this content as part of an ASP.NET
site by including the XBAP, the EXE, and the manifest files that
resulted from the compilation in a folder in an ASP.NET application. You
do that shortly.