Beta Tutorial 5 Blend
Beta Tutorial 5 Blend
A Note on This Tutorial. The history of the material for this tutorial is
that Scott Guthrie wrote a terrific introduction to this material at the
end of February, which he gave me permission to turn into a series of
videos, currently (or soon to be) available on Silverlight.NET. This
tutorial completes the circle by building on the videos and integrating
the material into the Silverlight Tutorial series.
The project we’re setting out to build is very similar to the Silverlight chat service built
by ScottGu, and is shown in Figure 5-1
Figure 5-1. Completed Application
Getting Started
The best way to get started is by opening Expression Blend.
The first thing you’ll see is the New Project window. Choose Silverlight 2 Application,
set your language to Visual Basic and choose a location for your new project, which we’ll
name BlendForSilverlight, as shown in Figure 6-2
Figure 5-2. Creating the New Project
The Chevron tool allows access to all the controls, including any user controls, custom
controls or third party controls (be sure to click Show All) as shown in Figure 6-6
If your mouse doesn’t have a wheel, you can zoom by picking a value
(or filling in an arbitrary value) at the bottom of the design window or
by using the menu choices View→Zoom In and View→Zoom Out
You can move the surface by clicking on the hand and then using the mouse to click and
drag or by using the scroll bars.
Take a look at the upper right hand corner of your grid, as shown in figure 6-7
Immediately after I click, an open lock appears above and below my new row line. I’ll
add two lines, one for the top row and one for the bottom; thus implicitly creating a
middle row, and thus three locks as shown in figure 6-9.
Figure 5-9. Creating the bottom row
Note that immediately after the row is created, not only are the locks shown but the
cursor changes shape to indicate that you can easily move, and thus resize the rows.
The open locks indicate that the rows will resize as the browser (inside of which your
Silverlight application will run) is resized. We want the middle row to do so, but we want
the top and bottom row to remain of fixed size, so click on the top and bottom lock, and
then click on split view to examine the effects on the XAML, as shown in figure 6-10.
Figure 5-10. Middle Row has Star Sizing
Note that (on line 10) the middle row definition has its Height property set to * (star)
indicating that it will take up the remaining room after the other rows are allocated.
The value you put in a property box does not take effect until you leave
that box (e.g., using tab)
There are a few things to notice about the Layout Panel (figure 6-12)
Figure 5-12. Setting the Button Layout with the Layout Panel
First, you can set the Width and/or Height to auto by pressing the button to the right of
the field. Second, when you set a specific (non-default) value next to a property, a white
dot appears (there are 5 white dots in Figure 6-12).
Take a look at the Xaml once you have these values set,
<Button HorizontalAlignment="Stretch" Margin="4,4,4,4" VerticalAlignment="Stretch"
Grid.Column="1" Grid.Row="2" Content="Button"/>
Blend has translated your choices into Xaml that will create the look you’ve chosen. We
have, however, forgotten to change the “Content” property from Button to “Send”. The
easiest way to do so is to type Content into the property Search box,
At “co” you will get back “Column”, “Horizontal Content”, “Data Content” and
“Content” as shown in Figure 6-13
Some (few) controls have a text property and most have a content
property. Those with a content property often fill that property with
text, but they are free to fill it with almost anything else, including
other controls. This is demonstrated in the Tutorial on Styles and
Templates
Figure 5-15. Setting the Font Family and More
Creating The Rounded Rectangle Input Area
Examining the finished application shown at the top of the tutorial reveals that the input
area has a rounded rectangle as shown in figure 6-16
You can now easily populate your list box with dummy list items,
<ListBox Height="Auto" Width="Auto" x:Name="Conversation" >
<ListBoxItem Content="Jesse: Is this working?" />
<ListBoxItem Content="Scott: Of course." />
<ListBoxItem Content="Jesse: I'm following the directions." />
<ListBoxItem Content="Scott: Then you should be fine." />
<ListBoxItem Content="Jesse: Great, thanks." />
</ListBox>
Save your file and switch back to Blend (no need to close Visual Studio 2008). When you
do, Blend lets you know the files were modified,
Figure 5-22. Blend letting you know the files were modified
Click yes, and your dummy data should be visible.
You can press F5 to run the program as an interim check. You’ll find that the image
doesn’t appear unless you place a copy of the image file in the bin/debug directory as
well. That’s not a big problem, however, as we’ll be binding to the source for the image
file.
Once in Visual Studio 2008 right click on the project and choose Add Class. In the new
items dialog select class and name your new class ChatMessage as shown in figure 6-24
The Chat Message class is pretty straight forward, consisting only of two properties,
Public Class ChatMessage
Private privateUserName As String
Public Property UserName() As String
Get
Return privateUserName
End Get
Set(ByVal value As String)
privateUserName = value
End Set
End Property
Private privateText As String
Public Property Text() As String
Get
Return privateText
End Get
Set(ByVal value As String)
privateText = value
End Set
End Property
End Class
The ChatSession is somewhat more complex, but we’ll simplify greatly by stubbing out
all the difficult parts.
We begin by marking the class as implementing INotifyPropertyChanged, which as noted
in the DataBinding Tutorial ensures that the UI fields will be updated as the data changes.
Public Class ChatSession
Implements INotifyPropertyChanged
This interface requires only that we provide a PropertyChangedEventHandler that
implements the PropertyChanged event,
Public Event PropertyChanged As PropertyChangedEventHandler Implements
INotifyPropertyChanged.PropertyChanged
The class has two straight forward public properties: one for the user’s name, and one for
the URL of the user’s Avitar (image),
Private privateRemoteUserName As String
Public Property RemoteUserName() As String
Get
Return privateRemoteUserName
End Get
Set(ByVal value As String)
privateRemoteUserName = value
End Set
End Property
Private privateRemoteAvatarUrl As String
Public Property RemoteAvatarUrl() As String
Get
Return privateRemoteAvatarUrl
End Get
Friend Set(ByVal value As String)
privateRemoteAvatarUrl = value
End Set
End Property
Next we want to create a collection of the ChatMessages. What we want, however, is to
raise an event each time the collection changes (e.g., a message is added) and we want
the list box to respond to that event. We could create all of that, but the framework makes
it easy. Listbox already knows to respond to PropertyChanged events, and there is a
special collection type ObservableCollection(of) that fires exactly that event every time
the collection is changed. This makes life a walk in the park,
Private privateMessageHistory As ObservableCollection(Of ChatMessage)
Public Property MessageHistory() As ObservableCollection(Of ChatMessage)
Get
Return privateMessageHistory
End Get
Friend Set(ByVal value As ObservableCollection(Of ChatMessage))
privateMessageHistory = value
End Set
End Property
Sending a message is now as simple as adding a new Chat message where the text is
taken from the message box and the user name is taken from the current user’s name (for
now, hard coded to “Me”)
Public Sub SendMessage(ByVal message As String)
' Todo: Send to remote chat server over sockets
Before we can send messages, however, we must connect with the remote user,
obtaining the remote user’s name, avatar and initializing the observable collection of
messages,
Public Sub ConnectWithRemoteUser(ByVal remoteUserName As String)
' Todo: 1) Wire-Up socket stack to receive notifications of received messages
' 2) Wire-Up to a remote avatar service instead of hard-coding my picture
RemoteUserName = remoteUserName
RemoteAvatarUrl = "jesse.jpg"
MessageHistory = New ObservableCollection(Of ChatMessage)()
End Sub
DataBinding
With these classes in place (you did build to make sure all is well, yes?) we’re ready to
data bind. Let’s do that in Blend (!)
Make sure you’ve saved all your files in Visual Studio 2008 but don’t close it, just switch
over to Blend. Say yes to the “something has changed when I wasn’t looking” dialog
(your wording may vary). Under the project panel you should see a Data panel, within
which is a tab marked CLR Object. Click on that and Hey! Presto! You will see Blend for
Silverlight that will open up to show a dialog that lets you add any CLR object as a data
source. Notice that ChatMessage and ChatSession are listed. Click on Chat session and
click OK and Chat SessionDS appears in your Data list, as shown in Figure 6-25.
This teaches the ListBox how to display each of the list items, specifying that each will
be dislayed with three TextBlocks, aligned horizontally by a stack panel, as shown in
figure 6-29
Figure 5-29. Data Template at work
Adding Templates
The Listbox and especially the Start Button don’t quite look the way we’d like. In the
previous version of this tutorial we fixed them with hand-written templates, but Blend
now offers a far better solution, which we will introduce in the next tutorial, so we’re
going to leave this as it is for now (not quite done, but a good way towards a solid
introduction to using Blend and Visual Studio together for programming an application).
Better not to finish, than to show you what amounts to an obsolete and inferior way of
solving the problem. In the interim, both Tim Heurer and I and many others will be
blogging about the new approach to Templates, and we’ll have the full tutorial out within
a few weeks.