User Interface Design with Silverlight
IMPROVING THE USER EXPERIENCE
Topics Manipulating Silverlight element properties Editing the XAML for Silverlight elements Using the MessageBox class Adding and using assets Assets as Content and Resources
Silverlight Elements At the moment we know about three elements
TextBlock to display messages and labels TextBox to receive input from the user Button to generate events
In this session we are going to improve our understanding of these elements to create more interesting user interfaces
4
Elements as objects with properties
From a programming perspective we regard a Silverlight display element as an object
The object is an instance of the particular element type
We can call methods and set properties on the object
These can result in a change in the appearance of the object on the display
5
TextBlock properties
To change the text displayed by a TextBlock we just have to assign a string to the Text property
Behind the property will be some code that runs when the property is assigned
This will tell Silverlight that the text has changed and will result in the display updating
We don’t have to worry about how this works
6
resultTextBlock.Text = result.ToString();
Improving Error Handling At the moment our AddingMachine program is not tolerant of user errors
If they enter text rather than a number into a TextBlock the Parse method will throw an exception and the program will halt
7
Parse and Exceptions
The Parse method will throw an exception if we give it invalid inputs
Our program must deal with this more gracefully than just stopping
8
float v1 = float.Parse(firstNumberTextBox.Text);
Using TryParse to detect errors
The TryParse method will try to parse the string The clue is in the name
If the parse fails it returns false It will not throw an exception
9
float v1 = 0;
if (!int.TryParse(firstNumberTextBox.Text, out v1))
{
// Invalid text in textbox
}
Using the out parameter
TryParse is given a reference to the location where it must place the result
This is an out parameter The method is passed a reference it can
follow to put the result into v1
10
float v1 = 0;
if (!int.TryParse(firstNumberTextBox.Text, out v1))
{
// Invalid text in textbox
}
Changing the colour of Text
This version of the number conversion code turns the colour of the text in the TextBox red if the number is invalid
11
float v1 = 0;
if (!float.TryParse(firstNumberTextBox.Text, out v1))
{
firstNumberTextBox.Foreground =
new SolidColorBrush(Colors.Red);
return;
}
Drawing and Brushes
The text is drawn using a Silverlight brush The simplest form of brush is a solid colour,
but you can make bushes from images and gradients
12
float v1 = 0;
if (!float.TryParse(firstNumberTextBox.Text, out v1))
{
firstNumberTextBox.Foreground =
new SolidColorBrush(Colors.Red);
return;
}
13
Demo 1: Faulty Number Validation
Demo
Brush setup
This solution uses two brushes One is set to the error colour, Red The other is copied from the TextBox so that we
can use it to put the colour back if the entry is valid
14
private SolidColorBrush errorBrush =
new SolidColorBrush(Colors.Red);
private Brush correctBrush = null;
Storing the correct brush
The first time the method is called it makes a copy of the brush used in the TextBox
15
private void calculateResult()
{
bool errorFound = false;
if (correctBrush == null)
correctBrush = firstNumberTextBox.Foreground;
// Rest of method goes here
}
Proper Error display
The text is drawn using a Silverlight brush The simplest form is a solid colour, but you can
make bushes from images and gradients
16
private void calculateResult()
{
// Sort out brushes
if (!float.TryParse(firstNumberTextBox.Text, out v1))
{
firstNumberTextBox.Foreground = errorBrush;
errorFound = true;
}
else
{
firstNumberTextBox.Foreground = correctBrush;
}
}
17
Demo 2: Working Number Validation
Demo
Further Improvement At the moment the text
keyboard is displayed when the user starts to enter the numbers to be added
This is not what they would like The number keyboard
should be displayed first
18
Editing the XAML for an element The XAML is the part of the program that “declares”
the Silverlight display elements that are used in the user interface on the page
We can modify the declaration to tell configure the TextBox to display the digital keyboard
This is the best place to perform such settings Although you could also do this using C# code if
you wanted to
19
TextBlock XAML
This is the XAML used to configure one of the TextBlocks in AddingMachine
These settings position the control on the page and set up the text alignment
We need to add the numeric keyboard requirement
20
<TextBox Height="72" HorizontalAlignment="Left" Margin="8,175,0,0"
Name="secondNumberTextBox" Text="0" VerticalAlignment="Top" Width="460"
TextAlignment="Center" />
XAML and attributes
The information about the TextBox is presently given as a series of attributes
You can think of an attribute as a simple name/value pair if you wish
These are given as part of a simple TextBox element
21
<TextBox Height="72" HorizontalAlignment="Left" Margin="8,175,0,0"
Name="secondNumberTextBox" Text="0" VerticalAlignment="Top" Width="460"
TextAlignment="Center" />
Attributes and InputScope The keyboard required for a TextBox is selected
using the “InputScope” information for that TextBox
The InputScope is actually a collection of InputScopeName values
This makes it hard to express the InputScope as an attribute to the TextBox
So we have to change the format of the XAML used to describe the TextBox
22
Configuring using attributes
In this format the attributes are given between the <TextBox and the /> delimiters
This is a great way to express simple items of configuration information
23
<TextBox Height="72" HorizontalAlignment="Left" Margin="8,175,0,0"
Name="secondNumberTextBox" Text="0" VerticalAlignment="Top" Width="460"
TextAlignment="Center"
/>
Configuring using properties
This version of TextBox configuration uses a property list as well as attributes
24
<TextBox Height="72" HorizontalAlignment="Left" Margin="8,19,0,0" Name="firstNumberTextBox"
Text="0" VerticalAlignment="Top" Width="460" TextAlignment="Center">
<TextBox.InputScope>
<InputScope>
<InputScopeName NameValue="Digits" />
</InputScope>
</TextBox.InputScope>
</TextBox>
Attributes
The attributes are in the same place as before But the TextBox now contains a list of properties
25
<TextBox Height="72" HorizontalAlignment="Left" Margin="8,19,0,0" Name="firstNumberTextBox"
Text="0" VerticalAlignment="Top" Width="460" TextAlignment="Center">
<TextBox.InputScope>
<InputScope>
<InputScopeName NameValue="Digits" />
</InputScope>
</TextBox.InputScope>
</TextBox>
Attribute delimiter
This character marks the end of the attributes for the TextBox
If there were no properties it would be />
26
<TextBox Height="72" HorizontalAlignment="Left" Margin="8,19,0,0" Name="firstNumberTextBox"
Text="0" VerticalAlignment="Top" Width="460" TextAlignment="Center">
<TextBox.InputScope>
<InputScope>
<InputScopeName NameValue="Digits" />
</InputScope>
</TextBox.InputScope>
</TextBox>
Properties
These are the properties for the TextBox At the moment we just have the one, which is a list
of InputScope items
27
<TextBox Height="72" HorizontalAlignment="Left" Margin="8,19,0,0" Name="firstNumberTextBox"
Text="0" VerticalAlignment="Top" Width="460" TextAlignment="Center">
<TextBox.InputScope>
<InputScope>
<InputScopeName NameValue="Digits" />
</InputScope>
</TextBox.InputScope>
</TextBox>
Property Delimiter
This marks the end of the properties for the TextBox
We could have lots of other properties
28
<TextBox Height="72" HorizontalAlignment="Left" Margin="8,19,0,0" Name="firstNumberTextBox"
Text="0" VerticalAlignment="Top" Width="460" TextAlignment="Center">
<TextBox.InputScope>
<InputScope>
<InputScopeName NameValue="Digits" />
</InputScope>
</TextBox.InputScope>
</TextBox>
Attributes in action
As another example, consider a Person described in XAML
This person has a name attribute We can express the attribute in the simple form
above This is a name/value pair
29
<Person name="Rob"/>
Adding Properties
Now the Person has both attributes and properties The Address has attributes and properties too
30
<Person name="Rob">
<Address addressType="HomeAddress">
<FirstLine text="18 Pussycat Mews"/>
<Town text="Seldom"/>
<County text="Wilts"/>
<PostCode text="NE1 410S"/>
</Address>
</Person>
Attributes vs Properties If you are holding a something simple and
indivisible about an element, for example Height = 72, then an attribute makes very good sense
If you are holding something that is compound (i.e. contains sub elements), for example a list of InputScopeNames , then properties make good sense
31
Properties
Since the input scope will contain a list of items it makes sense to use the Property format
32
<TextBox Height="72" HorizontalAlignment="Left" Margin="8,19,0,0" Name="firstNumberTextBox"
Text="0" VerticalAlignment="Top" Width="460" TextAlignment="Center">
<TextBox.InputScope>
<InputScope>
<InputScopeName NameValue="Digits" />
</InputScope>
</TextBox.InputScope>
</TextBox>
Attributes as Properties
We can actually express attributes as properties if we wish
The syntax is a bit long winded
33
<TextBox HorizontalAlignment="Left" Margin="8,175,0,0" Name="secondNumberTextBox" Text="0"
VerticalAlignment="Top" Width="460" TextAlignment="Center">
<TextBox.Height>
72
</TextBox.Height>
</TextBox>
XAML wrap up XAML “declares” the display elements and sets
their attributes and properties These are expressed in a customised form of XML Attributes provide a simple way of giving setting
information Properties are more structured They are equivalent, as they map onto properties of
a .NET class
34
Setting Properties in Code
This is the C# to do the same thing…
35
// Make a new input scope
InputScope digitScope = new InputScope();
// Make a new input scope name
InputScopeName digits = new InputScopeName();
// Set the new name to Digits
digits.NameValue = InputScopeNameValue.Digits;
// Add the name to the new scope
digitScope.Names.Add(digits);
// Set the scope of the textbox to the new scope
firstNumberTextBox.InputScope = digitScope;
36
Demo 3: Setting InputScope
Demo
Displaying a MessageBox If you want to display a message box to alert the
user of a situation, or ask for confirmation you can do this
The MessageBox class exposes a Show method that is used to display this
There are a number of options you can use to allow the user to confirm actions as well as acknowledge messages
37
Simple Message
You can create a multi-line message by breaking it with the Newline value
The Show method will not return until the user presses OK
38
MessageBox.Show("Invalid Input" +
System.Environment.NewLine +
"Please re-enter");
User Selection
You can test the return value and use this to control program behaviour
39
if (MessageBox.Show("Do you really want to do this?",
"Scary Thing",
MessageBoxButton.OKCancel) == MessageBoxResult.OK)
{
// do scary thing here
}
else
{
// do something else
}
Using Assets in Windows Phone We have seen that Visual Studio can use the project
mechanism to allow you to combine code and assets such as images and sounds
These can then be used in your program to improve the user experience
Now we are going to find out how to manipulate these from within a program
40
Adding an Asset The plan is to use this image
as the background to the AddingMachine program
It is a jpeg image that has been cropped from a larger picture
41
Image Sizes Remember that the Windows Phone is a slightly
constrained device Limited resolution screen (800x480) Limited amount of program memory
Make sure when you add images that you don’t add them to a greater resolution than is required for the platform Otherwise you will waste memory
42
Adding an Asset If we simply drag a file onto a
project that file is added to the project
A copy of the file is made in the project directory and the project contains a link to this copy
43
Linking to assets
You can use the Project>Add Existing Item dialog to add an asset
If you do this you can add the asset as a link rather than making a copy of it
This can be useful if you want several projects to share a single resource item
44
Assets Build Action When you add an asset to a
project you specify how it is to be used in the solution
This is set as the “Build Action” of the asset
The two Build Actions we are going to consider are “Content” and “Resource”
45
Assets as Content An asset with the “Build Action” of “Content” is copied into the folder alongside the program executable
The program can then open this file as it would any other
46
The Image element
Silverlight provides an Image element that will draw images on a page
The Image element has a source attribute that can identify a file of content to load the image from
47
<Image Height="611" HorizontalAlignment="Left" Margin="8,0,0,0"
Name="gearBackgroundImage" Stretch="Fill" VerticalAlignment="Top" Width="472"
Source="AddingGears.jpg" />
Silverlight Draw Order Silverlight will draw elements in
the order they are given in the XAML
If the image is drawn first it will have the other items drawn on top of it
48
49
Demo 4: A background as Content
Demo
Assets as Resources An asset added as a Resource is
stored as part of the program assembly file
The easiest way to add an image as a resource is to use the Visual Studio Toolbox to add an image
50
The Source property of an Image We can use the Source item in
the Properties pane for an image to create a resource to load
If we click the browse button we can open a Choose Image dialog
51
Image resources in the applicaiton We are now looking for
images held as resources in the application
At the moment there are not any
We can click Add to add an image as a resource
52
Browsing for image resources We can select one or more
images to be added into the application as resources
We could add other file types as well
53
An image resource Once the image is added it
has a particular path that can be used to locate it as a resource
This path will be added to the xaml for the Image element
54
Using a resource in an Image
This version of the source path locates the image as a resource in the assembly
When the Silverlight component is built it will now load the image from the assembly
55
<Image Height="611" HorizontalAlignment="Left" Name="gearBackgrounds" Stretch="Fill"
VerticalAlignment="Top" Width="472" Source="/AddingMachine;component/Images/AddingGears.jpg"
/>
56
Demo 5: A background as a Resource
Demo
Content vs Resources Content
Smaller program Faster load time for program, but slightly slower
access to the resource A bit more “untidy”
Resource Larger program Slower load time, but faster access to resources Just a single file to deploy
57
Review Silverlight elements have many properties that can
be manipulated by applications Initialisation properties are best set in the xaml for
an element Elements are described by attributes and properties A MessageBox is used to get a user response Assets are added to an application as content
(separate file) or resource (in assembly file)
58
DATA MANIPULATION AND DISPLAY
Topics Responding to events from Silverlight elements Using DataBinding to connect Silverlight elements
to application classes Adding classes as resources to a page One way data binding Two way data binding
Silverlight element events
We have seen how Silverlight elements can link to event handlers in the code for a page
61
private void equalsButton_Click(
object sender, RoutedEventArgs e)
{
calculateResult();
}
<Button Content="equals" Height="72" HorizontalAlignment="Left" Margin="158,275,0,0"
Name="equalsButton" VerticalAlignment="Top" Width="160" Click="equalsButton_Click" />
The TextChanged Event A Button can generate Click events when it is
clicked A TextBox can generate TextChanged events if the
user types in the TextBox We can use this to create an AddingMachine that
updates automatically No need to press Calculate each time a new
solution is required
62
TextBox Events The TextBox can generate lots
of different events We can create a binding to an
event by double clicking the event in the Properties pane
This updates the xaml description of the control and adds an event handler
63
Automatically calculating a result
Each time the text in the first number TextBox changes the calculation is performed
We can also bind an event to changes in the second TextBox too
64
private void firstNumberTextBox_TextChanged(
object sender,TextChangedEventArgs e)
{
calculateResult();
}
Double TextChanged Events
There is a known issue with the TextChanged event. It may get fired twice
This code shows how to work round this
65
string oldFirstNumber = "";
private void firstNumberTextBox_TextChanged(
object sender, TextChangedEventArgs e)
{
if (firstNumberTextBox.Text == oldFirstNumber) return;
oldFirstNumber = firstNumberTextBox.Text;
calculateResult();
}
66
Demo 1: Auto update AddingMachine
Demo
Data Binding This is a very important subject It provides a coupling between the data in a
program and the user interface It removes the need to write “glue” logic to link
program data to display elements It can work in two ways
‘One-way’ ‘Two-way’
67
One Way Data Binding This creates a connection between a property in a
display object and a property in a C# class If the property in the class is changed, the property
in the display element is changed too We can use this in our AddingMachine to bind the
result of the calculation to the display on the page
68
Two Way Data Binding This form of connection works in both directions
Changes to the display element fire events in the C# class
Changes to properties in the C# class cause the display element to update
We can use this in our AddingMachine to read numbers in from the user
69
Creating an Adder class The first thing we need to do is create a class that
encapsulates the behaviour of the AddingMachine This will expose the properties that we can bind to
the display elements Text in the top TextBox Text in the bottom TextBox Text in the result TextBlock
70
Creating an object to bind to
71
public class AdderClass
{
private int topValue;
public int TopValue
{
get { return topValue; }
set { topValue = value; }
}
// repeat for bottomValue
public int AnswerValue
{
get { return topValue + bottomValue;}
}
}
The AdderClass The AdderClass is the element in our program that
will do all the business logic We could give it to another programmer to fill in
and they could put the behaviours behind the properties in the class We could also create test versions to test the
display This is another example of separation of the
program from the presentation
72
Adding Notification Behaviour
For a class to be able to bind to display elements it must implement the INotifyPropertyChanged interface
This is how elements can register an interest in properties in the class
73
public interface INotifyPropertyChanged
{
// Summary:
// Occurs when a property value changes.
event PropertyChangedEventHandler PropertyChanged;
}
Silverlight display elements
When a Silverlight display element wants to be notified of a change to a property it will bind to the PropertyChanged event
The data object can then use the event to deliver a message that a property has changed
Above we are telling Silverlight the AnswerValue has changed
74
PropertyChanged(this,
new PropertyChangedEventArgs("AnswerValue"));
Reading back the property
When the Silverlight element reads the property it causes the result to be calculated and returned
This value will end up on the display
75
public int AnswerValue
{
get
{
return topValue + bottomValue;
}
}
76
Demo 2: AddingMachine with data binding
Demo
Binding a class to the xaml
The C# business class must be bound to the xaml in a page so that the page can use it
We start by adding the namespace containing the class to the resources available to this page
A xaml file contains a list of the namespaces it is using
77
xmlns:local="clr-namespace:AddingMachine"
Mapping a class to a resource
The next step is to make a mapping between the AdderClass and the name we are using in the xaml page In this case we are using the same name for both You might want to use different classes or test
classes in the xaml page This lets you configure this in the xaml
78
<phone:PhoneApplicationPage.Resources>
<local:AdderClass x:Key="AdderClass" />
</phone:PhoneApplicationPage.Resources>
Adding the resource to an element
The Grid control is the one that holds all the elements on our page
Adding a DataContext to a control makes it available to all the controls it contains
This means that our TextBlock and TextBox items can now all use that control
79
<Grid x:Name="LayoutRoot" Background="Transparent" DataContext="{StaticResource
AdderClass}">
Business Objects and Silverlight We have now connected our AdderClass business
object to Grid element and all the components in it We only have to do this once for a class, no matter
how many properties it contains The next thing we need to do is bind the Silverlight
element properties to the properties exposed by the AdderClass object
80
Binding the top line to AdderClass We are going to connect the
Text in the first number textbox (the one in the top line) to the TopValue property in AdderClass
We do this from the Properties pane in Visual Studio
81
Applying Data Binding If we select “Apply Data Binding” we are given a list of data sources and properties they expose
We select the one we want to use
Note that we have selected TwoWay binding
82
One Way binding for the answer When we bind the result text
box this is only bound “OneWay” There is no set method for
this property in
AdderClass The program will only ever
want to display results The binding can only be One Way
83
Review Silverlight elements can generate events that C#
code can bind to This includes changing text in a TextBox
Silverlight elements properties can also be bound to properties in C# business objects The object implements an interface that exposes
an event source that Silverlight can bind to This can provide two way (input/output) or one way
(output only) data binding
84
PAGES AND NAVIGATION
Topics Creating multi-page applications Navigating between pages Using the Back button Passing data between pages Page navigation events Sharing data in an application
Multi-page applications You often can’t fit all the required elements of an
application on a single page Alternatively you might want to have separate
“options” or “settings” pages in your application Silverlight on Windows Phone lets you add
additional pages to an application and allow the user to navigate between them
Before you write the code you should “storyboard” the application and forms
87
Adding another page
You add another page as you would any other item to a project
This creates the xaml and the C# code file
88
Pages and projects Pages that are added are
stored in the same project as the main page
They will be compiled and transferred into the target device automatically
89
Page Navigation
The NavigationService object performs navigation for an application
Each Silverlight page has a Uri The Navigate method takes the user to the
specified page
90
private void page2Button_Click(object sender,
RoutedEventArgs e)
{
NavigationService.Navigate(new Uri("/PageTwo.xaml",
UriKind.RelativeOrAbsolute));
}
The UriKind
The address of a resource can be expressed absolutely, or relative to the location the program is running from
RelativeOrAbsolute will work, but the navigation in this case is actually Relative
91
private void page2Button_Click(object sender,
RoutedEventArgs e)
{
NavigationService.Navigate(new Uri("/PageTwo.xaml",
UriKind.RelativeOrAbsolute));
}
Missing page exceptions The uri to the destination page is a string of text It is not a binding to a particular software object If you spell the uri incorrectly the Silverlight will
compile correctly and start running The program will throw an exception if an incorrect
uri is used to locate a page
92
Using the Back button The Back button is used on the Windows Phone to
move backwards through the UI This behaviour is built into Silverlight page
navigation on the device If the user presses Back they are automatically
taken to the previous Silverlight page If they press Back at the top level of the pages the
program is ended
93
Overriding the Back button You often want to get
control when a user tries to move off a page You might want to
confirm a save at that point
You can bind an event to the Back key pressed event which can do this
94
Disabling the Back Button
The event handler for the back button can cancel the back event
Binding the above method to the back button stops it from allowing navigation away from a page
95
private void PhoneApplicationPage_BackKeyPress(
object sender,
System.ComponentModel.CancelEventArgs e)
{
e.Cancel = true;
}
Using a MessageBox
This code adds a confirmation message
96
private void PhoneApplicationPage_BackKeyPress(
object sender,
System.ComponentModel.CancelEventArgs e)
{
if (MessageBox.Show("Do you really want to exit?",
"Page Exit",
MessageBoxButton.OKCancel)
!= MessageBoxResult.OK)
{
e.Cancel = true;
}
}
97
Demo 1: Multi-page navigation
Demo
Passing data between pages Each Silverlight page is a separate entity The code behind the page can hold data members
but these are local to that page You often want to pass data from one page into
another If the data is very simple you can just add it to the
uri that is used to locate the page
98
Assembling a data uri
This event handler adds a data item onto the uri that is passed into the destination page
It reads text out of a textbox and appends that to the uri
The data is labelled as info
99
private void page3Button_Click(object sender,
RoutedEventArgs e)
{
NavigationService.Navigate(
new Uri("/PageThree.xaml?info=" + InfoTextBox.Text,
UriKind.Relative));
}
Page navigated events If the destination page is to use the data in the uri
there must be a way of running some code when a page is navigated to
Silverlight provides methods to override in a page that give control when the page is navigated to and from
We are going to use the OnNavigatedTo event
100
Loading data from the uri
The NavigationContext object has a QueryString property
TryGetValue will search for a value in the uri and return true if it has found the value
101
protected override void OnNavigatedTo
(System.Windows.Navigation.NavigationEventArgs e)
{
string info = "";
if (NavigationContext.QueryString.TryGetValue("info",
out info) )
infoTextBlockFromQuery.Text = info;
}
102
Demo 2: Passing Data
Demo
Sharing objects between pages Each page in a program is a separate entity
It has its own member data, but is not able to refer to any other
When the program navigates to a page it does not provide a reference to the source page
To share data amongst pages we have to use the App.xaml object
103
The App.xaml page This is the ‘container’ for the
whole application It does not describe a page to
be drawn, but it does hold methods that start the application running
It also contains some event handlers
104
The App class
The App class for an application is an extension of the Application class provided by Silverlight
We can add our own members to this new class Here I have added a string data member
105
public partial class App : Application
{
// To be used from all pages in the application
public string LoginName;
}
Getting a reference to the App
The Current property of the Application class provides a reference to the currently active application It is provided as a reference to an Application
instance We need to convert this into a reference to the App
class that contains the data
106
App thisApp = App.Current as App;
LoginTextBox.Text = thisApp.LoginName;
107
Demo 3: Shared Data
Demo
Review You can create multiple Silverlight pages and add
them to your project Navigation to pages is performed on the basis of uri
(Uniform Resource Indicator) values The back button normally navigates back to the
source page, but this can be overridden The uri can contain simple text messages Pages can share larger objects in the App.xaml
page
108
EXERCISE 1: ADDING ERROR HANDLING
EXERCISE 2: IMPROVING THE USER INTERFACE
USING DATA BINDING
Top Related