microsoft word - building windows presentation foundation applications csharp part 1
TRANSCRIPT
Building Windows Presentation Foundation Applications - C# - Part 1
Microsoft® Virtual Labs
Building Windows Presentation Foundation Applications - C# - Part 1
Table of Contents
Building Windows Presentation Foundation Applications - C# - Part 1 ................................. 1
Exercise 1 Creating a WPF Application ........................................................................................................................ 2
Exercise 2 Data Binding to a Collection Object .......................................................................................................... 13
Lab Summary .............................................................................................................................................................. 15
Building Windows Presentation Foundation Applications - C# - Part 1
Page 1 of 15
Building Windows Presentation Foundation
Applications - C# - Part 1
Objectives After completing this lab, you will be better able to:
� Develop a basic WPF application
� Use a NavigationWindow and page functions to create a wizard
� Learn how Property Bags are used
� Data bind to a collections object
Estimated Time to Complete This Lab
45 Minutes
Computer to Use Vista
Building Windows Presentation Foundation Applications - C# - Part 1
Page 2 of 15
Exercise 1 Creating a WPF Application
Scenario There are two main types of applications you can build using the Windows Presentation Foundation: Installed
applications and Web Browser applications. The main differences between the types are in how they are hosted,
what security restrictions they must operate under, what application object they are associated with, and whether
they allow you to navigate from page to page. Each type of application has a corresponding Microsoft Visual Studio
2005 template that you can use to start implementing the application. In this lab, we will create an Installed
application. These applications are installed on the user's system with ClickOnce or MSI and hosted in a standalone
window. They have full access to the user's system resources and must have user’s consent before they can be
deployed.
In this exercise, you will develop a basic Address Book application with minimal functionality. You will learn how
to create basic UI, use Property Bags to pass information from one page to another, and write some application
logic. The application UI will show multiple examples of how to trigger the creation of a contact: via menu items,
context menu items, and toolbar buttons.
You will be able to find codes snippets used for this exercise under C:\Microsoft Hands-On Labs\DEV007
Building WPF Applications\codesnippets\CSharp\Exercise 1 Task 1 & Exercise 1 Task 2. The bolded codes in
the code section are the changes you need to make in your code.
Tasks Detailed Steps
Complete the following 2
tasks on:
Vista
1. Create a basic
application
a. Launch Microsoft Visual Studio 2005.
b. Create a new project using the C# “Windows Application (WPF)” project template
in Visual C# Net Framework 3.0. Name it ‘AddressBook’. This will create the
skeleton for our installed application.
c. The Address Book application will help you manage your Contacts. Add a new C#
class to your project. You can do this via the Solution Explorer by right-clicking
on the ‘AddressBook’ project, then choosing Add ���� New Item and then
selecting ‘Class’ from the dialog. We’ll call it Contact.cs and this will have our
data model: Code Snippet (code1.txt)
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Data;
using System.Collections.ObjectModel;
namespace AddressBook
{
/// <summary>
/// Contact value object
/// </summary>
public class Contact
{
private String firstName;
private String lastName;
private String emailAddress;
private Uri homePageUri;
Building Windows Presentation Foundation Applications - C# - Part 1
Page 3 of 15
Tasks Detailed Steps
private string homeAddress;
private string businessAddress;
/// <summary>
/// First name of contact
/// </summary>
public String FirstName
{
get { return firstName; }
set { firstName = value; }
}
/// <summary>
/// Last name of contact
/// </summary>
public String LastName
{
get { return lastName; }
set { lastName = value; }
}
/// <summary>
/// Email address of contact
/// </summary>
public String EmailAddress
{
get { return emailAddress; }
set { emailAddress = value; }
}
/// <summary>
/// Home page
/// </summary>
public Uri HomePage
{
get { return homePageUri; }
set { homePageUri = value; }
}
/// <summary>
/// Home address
/// </summary>
public string HomeAddress
{
get { return homeAddress; }
set { homeAddress = value; }
}
Building Windows Presentation Foundation Applications - C# - Part 1
Page 4 of 15
Tasks Detailed Steps
/// <summary>
/// Business address
/// </summary>
public string BusinessAddress
{
get { return businessAddress; }
set { businessAddress = value; }
}
}
/// <summary>
/// This collection will hold all of our contacts in
the
/// address book
/// </summary>
public class ContactList :
ObservableCollection<Contact>
{
public ContactList()
: base()
{
}
}
}
Note: You will notice that the ContactList class derives from
ObservableCollection<T> and thus provides the main data context with a bindable
data collection. The DataContext property on an element is used to specify the source
data for the binding. By binding to data grouped into collections using WPF data
collections features, your application can automatically respond to changes in
individual data items in the collection as well as to changes in the collection as a
whole. Alternate views on data collections can be constructed to support sorting,
filtering, and navigating over the collection, without necessarily modifying the content
of the collection. The ObservableCollection<T> class is Windows Presentation
Foundation’s built-in implementation of a data collection. Exercise 2 will focus on our
data binding implementation.
d. Now let’s define a set of contacts. You will need to add a new text file to your
project and call it contacts.txt. You can do this via the Solution Explorer by right-
clicking on the project, then choosing Add ���� New Item and then selecting ‘Text
File’ from the dialog. Copy the following content over to that file: Code Snippet
(code2.txt)
Joe;Developer;[email protected];http://spaces.msn.com;1
North First St, Redmond, WA 98052; 2 South First St,
Redmond, WA 98052
Jane;Tester;[email protected];http://spaces.msn.com;101
Baker St, Bellevue, WA 98055; 202 Smith St, Redmond, WA
98052
Note: The contact information consists of two entries each on a separate line. Once
the contacts.txt file is created, select it in the Solution Explorer. Its properties should
Building Windows Presentation Foundation Applications - C# - Part 1
Page 5 of 15
Tasks Detailed Steps
show up in the Properties window below. If they do not show up, right-click the file
and select Properties. Notice that the Build Action property has the value ‘Content’.
This tells the WPF MSBuild system to treat this file as loose content accompanying the
application. The Copy to Output Directory property has the value ‘Do not copy’.
Change this to ‘Copy if newer’. This will ensure that the contacts.txt file is copied
over to the build’s output directory if changes are made to it.
Figure 1.1 Properties for loose content file contacts.txt
e. To allow us to have more control over what happens when the application starts
and exits, we will handle the Application Startup and Exit events. Add the
following code to App.xaml.cs: Code Snippet (code3.txt)
public App()
{
}
void AppStartup(object sender, StartupEventArgs args)
{
Window1 mainWindow = new Window1();
mainWindow.WindowStartupLocation =
WindowStartupLocation.CenterScreen;
mainWindow.Show();
}
private void AppExit(Object sender, ExitEventArgs e)
{
}
f. Double click on MyApp.xaml to view the XAML and add the following markup
to MyApp.xaml so that the Startup event is wired up to the code. You will also
need to remove the StartupUri property so that the Startup event code can handle
the loading of Window1. Code Snippet (code4.txt)
<Application
Building Windows Presentation Foundation Applications - C# - Part 1
Page 6 of 15
Tasks Detailed Steps
x:Class="AddressBook.App"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presen
tation"
StartupUri="Window1.xaml"
Startup="AppStartup"
Exit="AppExit" >
<Application.Resources>
</Application.Resources>
</Application>
g. Let’s create a basic UI. The UI will consist of a Window with a Grid which in
turn contains a DockPanel for each of the following: the menu bar, the toolbar, the
status bar, and the left-pane which lists your contacts. A frame on the right will
house the details information for the selected contact. In the Window1.xaml file,
we’ll start with a Grid and name it DocumentRoot: When you double click on
Window1.xaml, you will see xaml tab below along with Code and Design tab.
Click on XAML Tab to edit xaml Code Snippet (code5.txt)
<Window x:Class="AddressBook.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presen
tation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="AddressBook"
Loaded="WindowLoaded"
SizeToContent="WidthAndHeight"
MinWidth="640"
MinHeight="480">
<Grid Background="White" Name="DocumentRoot">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="200"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<!-- Menu -->
<!-- Tool Bar -->
<!-- Content Area -->
<!-- Status Bar -->
</Grid>
</Window>
h. All of our layout and form elements will be within the DocumentRoot Grid. Next,
create the DockPanel_Menu which will enclose the menu bar. We will have two
top-level MenuItems: File and Edit, each with several child MenuItems. Code
Snippet (code6.txt)
Building Windows Presentation Foundation Applications - C# - Part 1
Page 7 of 15
Tasks Detailed Steps
<!-- Menu Bar -->
<DockPanel
Name="DockPanel_Menu"
Grid.Column="0"
Grid.ColumnSpan="2"
Grid.Row="0">
<Menu Background="White">
<MenuItem Header="File">
<MenuItem Header="New Contact"
Click="LaunchNewContactWizard"/>
<MenuItem Header="New Group"
Click="NotImplementedMsg"/>
<Separator />
<MenuItem Header="Properties"
Click="NotImplementedMsg"/>
<MenuItem Header="Delete"
Click="NotImplementedMsg"/>
<MenuItem Header="Import">
<MenuItem Header="Address book (WAB)..."
Click="NotImplementedMsg"/>
<MenuItem Header="Business card vCard)..."
Click="NotImplementedMsg"/>
</MenuItem>
<Separator />
<MenuItem Header="Exit" InputGestureText="Alt-F4"
Click="ExitApplication">
<MenuItem.ToolTip>
<ToolTip>
Click here to exit
</ToolTip>
</MenuItem.ToolTip>
</MenuItem>
</MenuItem>
</Menu>
<Menu Background="White">
<MenuItem Header="Edit">
<MenuItem Command="ApplicationCommands.Copy"/>
<MenuItem Command="ApplicationCommands.Paste"/>
</MenuItem>
</Menu>
</DockPanel>
i. The tool bar comes next. The ToolBar has two Buttons which allow you to add
and remove contacts. We’ll implement the add functionality later. The delete
function is a placeholder and is handled by the NotImplementedMsg handler
method we’ve previously defined. Code Snippet (code7.txt)
<!-- Tool Bar -->
<DockPanel
Name="DockPanel_Toolbar"
Grid.Column="0"
Grid.ColumnSpan="2"
Grid.Row="1">
<ToolBar>
Building Windows Presentation Foundation Applications - C# - Part 1
Page 8 of 15
Tasks Detailed Steps
<Button Click="LaunchNewContactWizard" ToolTip="Add
Contact">
+
</Button>
<Button Click="NotImplementedMsg" ToolTip="Delete
Contact">
-
</Button>
</ToolBar>
</DockPanel>
j. The left pane of the Address Book application’s main window must display a list
of your contacts. For this purpose, we’ll use a ListBox, with each Contact’s
FirstName as a ListItem entry. For now, let’s focus on the ListBox and the
DockPanel which encloses it. We’ll come back to the ListItems when we look at
data binding.While we are at it, let us also define a Context Menu for the list of
contacts. This will allow you to Add a Contact or Add a Group. Code Snippet
(code8.txt)
<!-- Left Pane for contact list view -->
<DockPanel
Name="DockPanel_LeftPane"
Grid.Column="0"
Grid.Row="2">
<ListBox Name="allContacts"
SelectionChanged="ListItemSelected">
<ListBox.ContextMenu>
<ContextMenu>
<MenuItem Header="Add a Contact"
Click="LaunchNewContactWizard"/>
<MenuItem Header="Add a Group"
Click="NotImplementedMsg"/>
</ContextMenu>
</ListBox.ContextMenu>
</ListBox>
</DockPanel>
k. Another key element of the main window’s UI is the status bar. This is achieved
by enclosing a TextBlock within a StatusBar element. Code Snippet (code9.txt)
<!-- Status Bar -->
<DockPanel
Name="DockPanel_Statusbar"
Grid.Column="0"
Grid.ColumnSpan="2"
Grid.Row="3">
<StatusBar
BorderBrush="Black"
BorderThickness="1">
<TextBlock Name="tb" Foreground="Black">
Status bar
</TextBlock>
</StatusBar>
</DockPanel>
l. The final piece of the basic application UI is the right hand side frame. When the
Building Windows Presentation Foundation Applications - C# - Part 1
Page 9 of 15
Tasks Detailed Steps
ListItems finally show up, clicking on one of them will display the contact’s
information in the Frame_RightPane. Code Snippet (code10.txt)
<!-- RightPanel -->
<Frame Name="Frame_RightPane"
Grid.Column="1"
Grid.Row="2"/>
m. Now that we've added the UI elements in the XAML page, it is time to move on to
the code-behind. In the Window1.xaml.cs file, add the ExitApplication,
NotImplementedMsg, WindowLoaded, ListItemSelected and
LaunchNewContactWizard methods in the body of the Window1 class. You will
notice that the latter 3 methods have empty bodies. We will add logic to these
methods later: Code Snippet (code11.txt)
//
// Triggered on Window load. Sets the ContactList
collection
// as the Data Context.
//
private void WindowLoaded(object sender,
RoutedEventArgs e)
{
}
//
// Triggers application shutdown
//
void ExitApplication(object sender,
RoutedEventArgs e)
{
this.Close();
}
//
// Shows a message box informing user that a
feature
// hasn't been implemented.
//
void NotImplementedMsg(object sender,
RoutedEventArgs e)
{
MessageBox.Show("This feature has not been
implemented.",
"Not Implemented");
}
//
// Triggered when an item in the Contacts list is
selected
//
void ListItemSelected(object sender,
SelectionChangedEventArgs args)
Building Windows Presentation Foundation Applications - C# - Part 1
Page 10 of 15
Tasks Detailed Steps
{
}
//
// Triggered when context menu or other toolbar
option
// is clicked to launch
// 'Create a new contact' dialog
//
private void LaunchNewContactWizard(object sender,
RoutedEventArgs e)
{
}
n. Build and run your application. You now have the skeleton of your Address Book
application. Since we haven’t initialized and used the contact information, you
won't see anything in the left and right panes. At this stage, you application should
look like this:
Figure 1.2 Basic Address Book application UI
2. Use Property Bag to
store the collection
of Contacts
a. Upon startup, the application must read the contact information from a file and
initialize the ContactList object. Open the App.xaml.cs file for editing. The
ReadContactsFromFile method reads data from a file. In the class body, add this
method and the helper method to de-tokenize entries. Code Snippet (code1.txt)
//
// Reads contact information from file
//
private ContactList ReadContactsFromFile()
{
ContactList contactList = new ContactList();
Building Windows Presentation Foundation Applications - C# - Part 1
Page 11 of 15
Tasks Detailed Steps
// Create an instance of StreamReader to read
from a file.
// The using statement also closes the
StreamReader.
using (StreamReader sr = new
StreamReader("contacts.txt"))
{
String line;
// Read and display lines from the file
until the
// end of the file is reached.
while ((line = sr.ReadLine()) != null)
{
contactList.Add(CreateContactFromLine(line));
}
}
return contactList;
}
//
// De-tokenize one line of contact information and
// hydrate a Contact object
//
private Contact CreateContactFromLine(string line)
{
string[] tokens = line.Split(new char[] { ';'
});
if (tokens.Length != 6)
{
throw new ApplicationException(
String.Format("Input contact file
format. " +
"Expected tokens {0}; Actual tokens
{1}", 6,
tokens.Length));
}
Contact contact = new Contact();
contact.FirstName = tokens[0];
contact.LastName = tokens[1];
contact.EmailAddress = tokens[2];
contact.HomePage =
(String.IsNullOrEmpty(tokens[3]) ?
null :
new Uri(tokens[3],
UriKind.Absolute));
contact.HomeAddress = tokens[4];
contact.BusinessAddress = tokens[5];
return contact;
}
Building Windows Presentation Foundation Applications - C# - Part 1
Page 12 of 15
Tasks Detailed Steps
b. The ReadContactFromFile method uses System.IO.StreamReader. Make sure you
add a using statement for it before the namespace declaration: Code Snippet
(code2.txt)
using System.IO;
c. The ContactList data returned by the ReadContactsFromFile method is added as an
entry in the application’s Property Bag. Modify the AppStartup method as shown
below: Code Snippet (code3.txt)
//
// Triggered on application startup. Positions the
window,
// Initializes the contact list model and adds it
to the
// Property Bag.
//
void AppStartup(object sender, StartupEventArgs
args)
{
// initialize the Contacts collection using
data from file
ContactList contactList =
ReadContactsFromFile();
// add it to the Property Bag
this.Properties["ContactList"] = contactList;
Window1 mainWindow = new Window1();
// make sure the window appears in the center
of the screen
mainWindow.WindowStartupLocation =
WindowStartupLocation.CenterScreen;
mainWindow.Show();
}
d. While we are at it, let’s also create a method to save the changes back to the
contacts.txt file. The logic is pretty straightforward and not really related to this
lab, so we won’t go into it. Code Snippet (code4.txt)
//
// Persists changes from ContactList object in
Property Bag
// to file.
//
private void SaveContactsToFile(string fileName)
{
}
e. Build and run the application. It should still look like it did in Figure 1.2. From the
UI it does not appear we are making any progress. Rest easy, we are!
Building Windows Presentation Foundation Applications - C# - Part 1
Page 13 of 15
Exercise 2 Data Binding to a Collection Object
Scenario WPF provides powerful data services which allow you to integrate data into your applications. UI elements can be
bound to data in CLR objects and XML sources. Data sources manage the relationship between data items (business
objects) and the various data binding capabilities of your application. There are several different types of data
sources for different source data types, including ObjectDataProvider and XmlDataProvider. Both implement the
IDataSource interface which provides a data source with the ability to notify its dependent bindings of changes to
the data object referred to by the data source.
In this exercise, you will learn how to data bind the contacts ListBox to the ContactsList collection present in the
property bag.
You will be able to find codes snippets used for this exercise under C:\Microsoft Hands-On Labs\DEV007
Building WPF Applications\codesnippets\CSharp\Exercise 2. The bolded codes in the code section are the
changes you need to make in your code.
Tasks Detailed Steps
Complete the following
task on:
Vista
1. Creating a one-way
binding
a. Define an ObjectDataProvider called “ContactList” as a resource in the
Resources section within the Window element in the Window1.xaml page. The
ObjectDataProvider’s type name is set to the namespace-qualified name of the
ContactList collection class. In addition, the name of the assembly, AddressBook,
is supplied to the MethodName attribute. Make sure you insert this
Window.Resources element above the Grid definition. When you double click on
Window1.xaml, you will see ‘Xaml’ tab below next to the ‘Design’ tab. Click on
‘Xaml’ tab to edit: Code Snippet (code1.txt)
<Window.Resources>
<ObjectDataProvider x:Key="ContactList"
MethodName="AddressBook.ContactList,AddressBook" />
</Window.Resources>
b. Styles allow an application, document, or user interface (UI) designer to
standardize on a particular look for their product. Further, data templates are used
to define the appearance of data. In order to style the UI for contact list data, you
must define a data template called “ContactNameTemplate” with a TextBlock
bound to the FirstName property of the Contact object in the ContactList. Code
Snippet (code2.txt)
<Window.Resources>
<ObjectDataProvider x:Key="ContactList"
MethodName="AddressBook.ContactList,AddressBook" />
<DataTemplate x:Key="ContactNameTemplate" >
<TextBlock Text="{Binding Path=FirstName}" />
</DataTemplate>
</Window.Resources>
Building Windows Presentation Foundation Applications - C# - Part 1
Page 14 of 15
Tasks Detailed Steps
c. We are ready to specify the ItemsSource for the allContacts ListBox as well as
assign the ContactNameTemplate. Code Snippet (code3.txt)
<ListBox Name="allContacts"
SelectionChanged="ListItemSelected"
ItemsSource="{Binding }"
ItemTemplate="{DynamicResource ContactNameTemplate}"
IsSynchronizedWithCurrentItem="True">
<ListBox.ContextMenu>
<ContextMenu>
<MenuItem Header="Add a Contact"
Click="LaunchNewContactWizard"/>
<MenuItem Header="Add a Group"
Click="NotImplementedMsg"/>
</ContextMenu>
</ListBox.ContextMenu>
</ListBox>
d. All that’s left is to set the value of the DockPanel_LeftPane’s data context to the
ContactList entry in the Property Bag. Add this line to the WindowLoaded method
in Window1.xaml.cs. Code Snippet (code4.txt)
DockPanel_LeftPane.DataContext =
Application.Current.Properties["ContactList"];
e. Browse into the folder where you saved your project. If you have saved in default
directory. Please go to C:\Users\User\Documents\Visual Studio
2005\Projects\AddressBook\AddressBook. Copy contacts.txt into the directory
bin\debug of the project.
f. If a dialog appears click Yes to continue.
g. Build and run your application. You should now see the application load with your
list of contacts populated in the ListBox on the left pane.
Building Windows Presentation Foundation Applications - C# - Part 1
Page 15 of 15
Tasks Detailed Steps
Figure 1.3 Basic Address Book application UI
Lab Summary In part 1 and 2 of this lab you performed the following exercises:
� Created a WPF application
� Bound an application UI element to data in a collection object
� Used Windows and Page Functions to create a structured navigation wizard
In part 1 and 2 of this lab, you learned how to use the WPF application model, its layout system, and other features
to build a sample Address Book application. In three exercises you developed the use cases for:
� Creating a contact with personal information (name, email, URL, IM address etc.) and home/business contact
information.
� Navigating to the Add Contact wizard in various ways (via menu item, context menu item and toolbar button).
� Listing all contacts in the address book.
� Listing detail information on selected contact.
� Actions associated with a contact, namely, sending email or viewing their homepage.