Saturday, June 6, 2009

More Silverlight Part 1 - Data Templates & Value Converters

I've pretty much finished up my Silverlight 2 project at work, so I thought I'd share a few more useful things that I've come across. This time, we'll take a look at Data Templates (which make List Boxes extremely flexible) and Value Converters.

Setting Up the App

We're going to start by building a application similar to what we built in the last few posts: a Silverlight 2 application that gets data from a WCF service. Start by following Steps 1 - 3 from this post. I'll point out where we'll make a couple of changes.

Step 1: Create a New Silverlight Application
We'll call it "TemplatesConvertersEvents" this time. Let it create the ASP.NET hosting site as well.

Step 2: Build a WCF Service

Step 2a: The WCF Service Contract
We'll create the same PersonService, but we'll add a new field "BirthDate" to the Person class. See the Service Contract below:

(Click image to enlarge)


Step 2b: The Service Implementation
Again, this will look pretty similar. We'll just add a BirthDate value to each of the Person objects.

(Click image to enlarge)


Step 2c: WCF Service Configuration
Same as last time. Make sure to change the binding from "wsHttpBinding" to "basicHttpBinding".

Step 3: Add the WCF Service Reference to the Silverlight Application

Step 4: Update the XAML.
This is pretty similar to the previous examples, with just a few differences. Check out the code sample below for Page.xaml. Then we'll walk through it.

(Click image to enlarge)


Start by changing the Width and Height properties of the page (500 x 300). Then replace the default Grid with a Border. The Border contains a 2 column grid. We'll be concentrating on the first column here (the 2nd column will be used in Part 2). The Grid contains a ListBox.

Notice that the ListBox looks a little different. We are no longer using the "DisplayMemberPath". Instead, we have an ItemTemplate that contains a DataTemplate. The DataTemplate is simply a container that can hold whatever content you like. For now, we'll just include a TextBlock that is bound to the FirstName field. This will have the same effect as if we were to set the DisplayMemberPath. One thing to be aware of: the DisplayMemberPath and ItemTemplate are mutually exclusive; if you try to include both, you will get an error.

Finally, we have a Button that looks similar to our previous examples. As a reminder, to add the Click handler, just type "Click=" and Visual Studio will pop up an option for "New Event Handler". This will create a handler based on the control name and put the stub in the code-behind.

Next we implement the handler. You can right-click on "GetPeopleButton_Click" and choose "Navigate to Event Handler" and it will take you to appropriate spot in Page.cs. The handler implementation should look like this (again similar to what we've seen before):

(Click image to enlarge)


Another reminder: you will need to add the "using" statement for the PersonService. If you type in the code above, you can place the cursor on "PersonServiceClient", then press Ctrl+. to bring up the option to add the "using".

You should be able to build and run the application now. After you click the button, the results should look like this:

(Click image to enlarge)


Expanding the Data Template
Now we'll see the power that the ListBox has by expanding the DataTemplate a bit. The DataTemplate can only have a single child element, so if we add multiple items, we'll need to wrap them in some sort of container. We'll use a set of nested StackPanels -- some vertical and some horizontal.

(Click image to enlarge)


This is fairly straightforward XAML. Note that we have multiple TextBlocks that are databound and a little bit of formatting. Here's what we get when we run the app now.

(Click image to enlarge)


Creating a Value Converter
One thing I don't like about the output is the format of the BirthDate field. To take care of this, we'll use a value converter. A value converter is simply a class that implements the IValueConverter interface (profound, eh?). The interface consists of 2 methods: Convert and ConvertBack. An incoming value is passed in as a parameter; all you need to do is do the conversion and return the new value.

Our DateConverter isn't going to be that interesting, but it's a good place to start (then we'll look at something a little more challenging).

In the Silverlight project, add a new Class. I've called mine "Converters.cs" because I'll use the same file to hold all of my converters. Then we'll rename the class from "Converter" to "DateConverter" and add the IValueConverter interface. IValueConverter is in the System.Windows.Data namespace, so you'll need to add this to the "using" block as well.

As we've done before, we'll just right-click on "IValueConverter", choose "Implement Interface", then "Implement Interface" again. This will put the "Convert" and "ConvertBack" method stubs into our class. We'll only be doing one-way conversion (read-only data), so we will only implement "Convert". If you had a TextBox or other editable control, then you would also implement "ConvertBack" which reverses the process. Here's our code:

(Click image to enlarge)


Since the "value" parameter is of type object, we'll need to start off by casting it to the inbound type that we are expecting (DateTime in this case). Our outbound type is simply a string, so we'll call the ToString function with a formatting string that we like. Note that there are additional options (some that are especially useful for Date conversions) by using the "parameter" and "culture" parameters. Take a look at the Microsoft Help file to get more information on those.

Using a Value Converter
So, now that we have a DateConverter, how do we use it? First, we'll need to add the namespace to our xaml (see below). Again, VisualStudio is helpful here; if you type "xmlsns:local=", then you will get a list of namespaces that are in the project, including everything that appears in the project References. We'll select the project namespace "TemplatesConvertersEvents". You can use whatever alias you like for the namespace; "local" is a convention for items contained within your project.

The next step is to add our DateConverter as a Static Resource.

(Click image to enlarge)


Now all that's left is to add the Converter to the Binding declaration in our TextBlock.

(Click image to enlarge)


If you run the application now, you'll see that we have a nicely formatted mm/dd/yyyy date for the BirthDate field. Let's try something a little more complex.

An Age Converter
In addition to the BirthDate, I'd like to display the age of the Person as well. The problem is that we don't have an Age field. So, instead, we'll use the BirthDate field to calculate the age. We'll just add another class (AgeConverter) to the Converters.cs file.

(Click image to enlarge)


We won't worry about the specifics of the code too much (I'm sure that I'll get letters with better ways to calculate age). The main point is that we are taking a DateTime (BirthDate) and converting it to an Integer (Age). Well, actually, we're converting it to a string for display purposes, but you get the idea.

Using the AgeConverter is just the same as the DateConverter. Add a Static Resource (I called mine "myAgeConverter") and then use it in a Binding statement. Notice that we are still Binding to the BirthDate field; by using the AgeConverter, we control what we will actually display. Here is a portion of our expanded DataTemplate (we appended the Age portions to the section with the BirthDate).

(Click image to enlarge)


If you run the app now, you'll see both the BirthDate and the Age are included.

One More Converter
As one final step, we'll get a little more creative with our converter. So far, we've more or less just converted a value from one format to another. This time, we'll convert to a completely different type. I want to display ages that are over 30 in a green font and 30 or under in blue. We'll do this by changing the BirthDate to a Brush.

Once again, create a new class "AgeBrushConverter" in the Converter.cs file. The code looks like the "AgeConverter" code, but instead of returning the age, it uses it to create a SolidColorBrush:

(Click image to enlarge)


For the implementation, our final "Resources" section looks like this:

(Click image to enlarge)


And our final DataTemplate (notice that we are using the AgeBrushConverter for the Foreground property of the TextBlock):

(Click image to enlarge)


And our final result:

(Click image to enlarge)


Summary
We've taken a chance to look at DataTemplates and ValueConverters to add flexibility to how we display our data in ListBoxes. DataTemplates can contain complex layouts (including Grids and Images, if desired). ValueConverters also go beyond simple formatting (like Dates and Currency); they can also be used to show or hide items (think of Binding a value to the "Visible" property) or even to add text formatting to differentiate values (such as using red for negative numbers and black for positive, or possibly graying-out inactive items).

Hang on to this application. In Part 2, we'll take a look at creating a custom user control that abstracts out part of the functionality and exposes an event that we can use.

Tuesday, May 12, 2009

Silverlight 2, WCF, and Lambda Expressions - Part 2

In Part 1, we set up a Silverlight 2 application that consumes a WCF Service. In Part 2, we'll look at a problem with the implementation and different ways of solving it -- ultimately ending with Lambda Expressions. Hopefully by the time we get done, you'll be comfortable with how lambda expressions work and how to use them to make your code cleaner and easy to understand.

Where We Left Off
Here's a quick reminder of what we did last time:
  1. We created a WCF Service that is Silverlight 2 compatible.
  2. We added a reference to the service in a Silverlight application.
  3. We created a UI (Button and ListBox) to call the service and show the results.
  4. We called the WCF Service and hooked up the Completed event to an event handler.

The Page.xaml.cs file we finished with is as follows:

(Click image to enlarge)

And the UI:

(Click image to enlarge)

A Problem
There is a small problem with the UI. After calling the service (by clicking the button), the list gets populated with the names. You can select a name in the list by clicking on it. But if you click the button again, the list refreshes and the selection goes away. We want to update this so that the selected item is maintained when the service is called again.

Solution #1 - Using the Event Handler
The SelectedItem of the ListBox gets cleared when the service is called because we are re-binding the data. From the ListBox's point of view, it is getting a new object to bind to. When the old object is un-bound, the selected item goes away and doesn't come back.

We'll solve this by simply saving off the SelectedIndex of the ListBox before we make the service call. Then after the service call returns, we will reassign the SelectedIndex. (This is assuming that the order of our items is not changing, and we're not getting any new items -- you can extend this basic functionality for more complex situations).

Since we need to save off the SelectedIndex in one method (the Button Click event handler) and then use it in a different method (the Service Completed event handler), we'll need to create a class-level variable to hold this information. See the code below:

(Click image to enlarge)


You'll see 3 new lines of code to get this to work:
  1. private int ehListIndex;
    The class-level variable
  2. ehListIndex = EHList.SelectedIndex;
    Saving the index
  3. EHList.SelectedIndex = ehListIndex;
    Re-assigning the index to the list box

If you re-run the application, you will see that if you make a selection in the list box, that selection is maintained when you call the service multiple times.

Solution #2 - Using an Anonymous Delegate
Now, we'll try this again using an anonymous delegate instead of an explicit event handler. You'll see why this is an advantage in just a bit.

We'll update our XAML by adding another StackPanel to our Grid.

(Click image to enlarge)

You'll notice that this section looks almost identical to the EventHandler UI section. Here's a summary of the differences:

  • The 2nd column of the Grid is specified in the StackPanel.
  • The Names of the ListBox and Button start with AD (for anonymous delegate) instead of EH.
  • The ListBox border is blue (just to make it different).
  • The button Content is "Anonymous Delegate".
  • There is a new Click handler for the button (you can look at the hint in Part 1 about letting IntelliSense create the handler for you).

So, what is an anonymous delegate? In our case, it is an in-line definition of an event handler (for the service callback). This is defined by using the "delegate" keyword, then a set of parentheses with the appropriate parameters, then a set of curly braces with the method implementation. The implementation will look just like in our callback when using the EventHandler.

Here's the initial implementation:

(Click image to enlarge)

What you will notice is that that the first and last lines are the same as our previous button click event. You'll also notice that the parameters for the anonymous delegate ("object" and "GetPeopleCompletedEventArgs") matches the parameters in the explicit event handler we implemented earlier. Finally, the body of the delegate matches the body of the event handler callback.

I know what you're thinking: big deal. Other than "in-lining" some code, exactly what did we gain here? We're about to find out.

We still have the same issue we had earlier with the ListBox SelectedIndex. The advantage to using an anonymous delegate is that any variables in the outer method can be accessed in the delegate implementation. This means that instead of using a class-level variable to store the index, we can use a local variable. Check out the completed code below:

(Click image to enlarge)


You'll see that we now have a local variable named "adListIndex" that is assigned outside of the delegate and then used inside of the delegate. We've just eliminated the need to have a class-level variable.

Solution #3 - Using a Lambda Expression
Let's take this one step further. Instead of using an anonymous delegate, we'll use a lambda expression. First, update the UI. This XAML is very similar to the anonymous delegate section:

(Click image to enlarge)


The same items are updated as above: grid column, element names, border color, button content, and click event.

So, now lets take a look at lambda expressions. There are 2 types of lambda expressions: statement lambdas and expression lambdas. Both use the same syntax (consisting of 3 parts):
  1. Parameters
    These are normally enclosed by parentheses (although, parentheses can be excluded if there is only a single parameter).
    The parameter types may be excluded if the compiler can determine the correct types.
  2. =>
    This is known as the "goes to" operator and denotes that this is a lambda.
  3. Statement(s) or Expression(s)
    A statement lambda has one or more operations wrapped in curly braces. The statement(s) denotes some type of work to be done.
    An expression lambda has one or more expressions (that return true or false) wrapped in curly braces. These are used extensively in LINQ.
    If there is only a single statement or expression, then the curly braces can be excluded.
We'll be working with an Statement Lambda. The first steps to convert the anonymous delegate to a lambda expression are to remove the "delegate" keyword and place the "=>" operator between the parameters and the method implementation. Take a look at the "LEButton_Click" method below and compare it to the first "ADButton_Click" method above:

(Click image to enlarge)


But, as we noted above, if the compiler can determine the parameter types, then we don't need to include them in our code:

(Click image to enlarge)


If you hover over the "s" and "ea" parameters, you will see that Visual Studio recognizes these as being of type "object" and "GetPeopleCompletedEventArgs" respectively. This means that we still have strongly-typed objects. The same is true of "ea.Result". This is the strongly-typed collection that is returned from our WCF Service.

As a final step, we can add the SelectedIndex handling code into the mix:

(Click image to enlarge)


If you run the application, you will see that all three list boxes behave the same way. All three list boxes will keep the selected index between service calls.
What We Learned
We took a look at 3 different ways to solve a particular UI issue. We see that both the Anonymous Delegate and Lambda Expression solutions have the advantage of being able to use a local-scoped variable (thus, keeping our class-level clutter-free). In addition, we see that the Lambda Expression solution has the advantage of not needing to include the parameter types. This is especially helpful if you have a delegate that has the standard 2 parameter signature ("object" and "SomeKindOfEventArgs"); you don't need to know the particular EventArgs class -- just let Visual Studio figure that out for you.
My advice: become familar with Lambda Expressions. You will find that when used judiciously, they can help keep your code understandable and easier to maintain.

Friday, May 1, 2009

Silverlight 2, WCF, and Lambda Expressions - Part 1

This is a 2-part series in using WCF with Silverlight 2. Part 1 is about creating a Silverlight-compatible WCF service and consuming it in a Silverlight application. Part 2 is about lambda expressions, but uses the foundations in Part 1.

Step 1 - Create a New Silverlight Application
First we'll create a new Silverlight application. In Visual Studio, create a New Project, and select the "Silverlight Application" template. I've called mine "SilverlightWithWCF", so that's what you'll see in a couple places throughout the post.

Visual Studio will prompt you with the following:
(Click image to enlarge)


We want to include a new ASP.NET Web Application Project, so we'll leave the defaults as-is. Other options include "ASP.NET Web Site" and possibly "ASP.NET MVC" (if you have the MVC bits installed). In addition to using the ASP.NET application as a test site for the Silverlight application, we will use it to host our WCF service.

Step 2 - Build the WCF Service
We'll add a new WCF Service at this point. Right-click on the Web Application project ("SilverlightWithService.Web" in my case), and choose "Add", then "New Item". Select the WCF Service. We'll name ours "PersonService.svc". See below:

(Click image to enlarge)


You'll notice that there are 2 options we could choose from: "WCF Service" or "Silverlight-enabled WCF Service". You might wonder why we didn't pick the Silverlight one. The answer is that I wanted to look at the standard WCF Service, so that you will know what to do if you already have an existing WCF Service that you want to hook into. I'll point out the difference below when we look at the Web.config file.

Step 2a - The WCF Service Contract
WCF Service consist of 3 main pieces: the Service Contract, the Service Implementation, and the Service Configuration. First, we'll look at the Service Contract.

The contract is simply an interface decorated with a few specific attributes. Visual Studio will create an I[ServiceName].cs file that contains the placeholder contract. If you open the IPersonService.cs file, you'll see an interface that is decorated with the [ServiceContract] attribute. Visual Studio also gives you a sample method called "DoWork". You'll notice that this is decorated with the [OperationContract] attribute. You can think of this as being analogous to the [WebMethod] attribute that we used in ASMX Services. The [OperationContract] attribute denotes which methods will be exposed to the outside world.

We're going to replace the "DoWork" method with a "GetPeople" method. Take a look at the completed code below, and we'll step through it:

(Click image to enlarge)


You'll notice that our method returns a List of Person. Person is a custom class, and so we need to include the definition of the class as well. You'll notice that we have a separate public class called "Person" that is decorated with the [DataContract] attribute. The class consists of 2 public properties (FirstName and LastName) that are each decorated with the [DataMember] attribute. The DataContract and DataMember attributes let the WCF sub-system know that it needs to include this type in the definition of the Service.

On a side note, the [DataContract] and [DataMember] attributes can be excluded in this particular case. .NET 3.5 SP1 will automatically include the type definition for public classes that have automatic properties and a public default constructor. This was added to facilitate Entity Framework. I'll leave it as an exercise for the reader to do further research into this.

The contract only tells what the service will do, not how it does it. For that, we'll need to look at the service implementation.

Step 2b - The WCF Service Implementation
The WCF Service implementation is a class that implements the WCF interface. Open up the "PersonService.svc.cs" file (note: you can simply double-click on the "PersonService.svc", and it will open the .cs file).

You'll see that the class "PersonService" implements "IPersonService" and still has the placeholder "DoWork" method from the stub that Visual Studio created. Delete this method. We'll let Visual Studio add the stubs for the updated interface. Simply right-click on "IPersonService" and select "Implement Interface", then "Implement Interface" again (we won't cover "Implement Interface Explicitly"). This will create a stub for the "GetPeople" method. Here's the implementation:

(Click to enlarge image)


This simply creates a List object and populates it with some Person instances. In real life, you'll probably be doing something more complex (such as accessing a database).

Next comes the configuration.

Step 2c - WCF Service Configuration
Open up the Web.config file, and then navigate to the "system.serviceModel" section (at the bottom). The only thing that you'll need to do is update the binding to "basicHttpBinding" (from "wsHttpBinding"). See below:

(Click image to enlarge)


Remember when I promised to show the difference between "WCF Service" and "Silverlight-enabled WCF Service"? This is it. Silverlight 2 is limited in that it can only use WCF Services that use the "basicHttpBinding". This is the same binding that ASMX services use. (Note: Silverlight 3 will not have this limitation). The "Silverlight-enabled WCF Service" defaults to basicHttpBinding, while "WCF Service" defaults to wsHttpBinding. If you have an existing service, you'll just need to change this value (or add an endpoint that uses this binding).

Note: This is a very important step. If you try to add a Service Reference in a Silverlight application to a WCF Service that is *not* using basicHttpBinding, then the proxy will not work. Even better, you don't get any helpful error messages, just a rather obscure one. So, make sure you don't skip this step.

From here, we'll build everything just to make sure that things look good. This completes our updates to the Web Application. Next, we'll move on to the Silverlight application.

Step 3 - Add the WCF Service Reference to the Silverlight Application
We'll start in the Silverlight application by adding a Service Reference to our newly created service. Right-click on the Silverlight Application project ("SilverlightWithService" in our case), and choose "Add Service Reference". If you click the "Discover" button, it will search out the Services that are included in the Solution. We'll use the namespace "PersonService". See below:

(Click image to enlarge)


Before you click "OK", be sure to check out the "Advanced" button. This opens a dialog that lets you choose how collections are returned from WCF Service calls:

(Click image to enlarge)


You'll see that there are 4 options to choose from: Array, Generic List, Collection, and ObservableCollection. The ObservableCollection is preferred in Silverlight for data binding purposes, but you may want to experiment with the other options as well. It doesn't matter the actual collection type that is returned from the service; it will be converted to the type you select here.

Now that we've added our Service Reference, we'll take a look at the Silverlight UI.

Step 4 - Update the XAML
Next, we'll create the UI. Open up the Page.xaml file. We're going to be making a few changes to the default values and adding some controls of our own. The final layout may look a little odd. This is because we will be adding some more elements to this in Part 2.

Here's the final layout:
(Click image to enlarge)


Let's look at the XAML; then we'll go through it step by step:
(Click image to enlarge)


First, update the Width and Height of the UserControl to 600 and 200 respectively. Then we'll swap out the "Grid" root element for a "Border". Then add a Grid with 3 columns (the other 2 columns will be used in Part 2). Inside the first column is a StackPanel with a ListBox and a Button. The ListBox sets the ItemsSource to "{Binding}". This says that each ListBox item will be bound to each item in the collection. The data binding will use a DataContext that we set in code at runtime.

Next is the Button named "EHButton" (for Event Handler Button -- Part 2 will have 2 additional Lists and Buttons and these names will make more sense). When adding an event handler in XAML, Visual Studio will help you out a bit. If you type "Click=" and hit Ctrl-Space (or let Intellisense pop up on its own), you will have the option "New Handler" to pick from. This will automatically name the handler based on the control name, and then add the stub to the code. In this case, it will create "EHButton_Click" in the code and hook up event.

Now that our UI is laid out, let's put the last of the pieces together.

Step 5 - Call the WCF Service
Here's another short-cut. If you right-click on "EHButton_Click" (the event handler) in the XAML, one of the options is "Navigate to Event Handler". This will open up the Page.xaml.cs file and put the cursor on the "EHButton_Click" event handler.

First, add the WCF Service namespace to the "using" section. This will make the code more readable. The namespace is [projectName].[serviceNamespace]. In our case, it is "SilverlightWithService.PersonService".

Now, we'll go back to the event handler. Start by creating a new proxy object. The proxy is the service name with "Client" appended to the end. In our case it is "PersonServiceClient". Next we'll hook up the callback. Since all Silverlight calls are asynchronous, we have to call the service asynchronously (it's the only choice). Start by hooking up an event handler to the "Completed" event. Visual Studio helps you out with this, too. Type "proxy.GetPeopleCompleted +=", and you'll see Intellisense for creating a new event handler. If you press "Tab" twice, it will create the new handler, and add the implementation. This is a great short-cut. The last step is to call the service using the "Async" method. In this case, just call "proxy.GetPeopleAsync()". See completed button click event handler below:

(Click image to enlarge)


The final step is to implement the callback. This is as simple as getting the result of the call (in this case a List of Person) with "e.Result" in the code. Then we assign this to the DataContext of the ListBox in the UI. One thing to note, if you hover over "e.Result", you will see that it is actually of type ObservableCollection of Person. This is due to the selection we made when we added the Service Reference earlier. The completed Page.xaml.cs file is as follows:

(Click image to enlarge)


Step 6 - Build and Test
Let's build and run. What you should see is that when you click the "Event Handler" button, you will get a list of 5 names in the ListBox. This may take a few seconds for the Service to fire up and run -- remember we're running asynchronously here. Also note that the list only includes the First Name because we did not do a full data template; we just set the DisplayMemeberPath. It's easy enough to enhance yourself, though.

(Click image to enlarge)

Conclusion
You should have a pretty good idea of how to create a WCF Service and consume it with Silverlight 2. We've created a new WCF Service, ensured that it was Silverlight 2 compatible, created a Silverlight 2 application, added the Service Reference, updated the UI, and finally called the Service and bound the results to the UI. In Part 2, we'll be looking at other ways of handling the asynchronous calls.

Tuesday, April 14, 2009

Book Review - Data-Driven Services with Silverlight 2

As mentioned in a previous post, I deal with data-centric applications on a daily basis. Data-Driven Services with Silverlight 2 by John Papa is an excellent book for folks in the same situation. Here's what I really like about it:
  • Focused Topic
  • Concise Code Snippets
  • Clear and Useful Samples
  • Full Coverage of Silverlight 2 Data Access

Let's take a look at each of these.

Focused Topic
The book covers only data access concepts in Silverlight 2. It assumes that you have a basic Silverlight background and does not focus on areas such as controls, XAML or layout. This keeps the book brief (around 350 pages) and allows you to focus on the relevant topic: data in Silverlight 2.

Concise Code Snippets
Code snippets are used liberally throughout the text, both XAML and C#/VB code. The snippets build on previous samples and so only show the "new" parts. This keeps the code snippets short and relevant. And even though the code shows both C# and VB, neither seems to be too long or distracting. I found myself even forgetting that the "other" language was included at times. (You should be able to figure out which language I'm referring to -- not that there's nothing wrong with it. Both languages are pretty much equivalent, so it's just a matter of preference when it comes to syntax.)

Clear and Useful Samples
The samples (downloadable from John Papa's webite) are very clear. When there are multiple examples covering a single topic, they are packaged into a single application. This makes it very easy to navigate the samples both at design-time and run-time.

(Click image to enlarge)

A couple things to notice in the screen-shot. First, the menu system on the left. This lists the different samples that are included in the project. This makes it very easy to flip back and forth to make comparisons among the samples.

Second, notice that the sample on the right is pleasant to look at. I know that this isn't really all that important. But, many times sample applications for data access methodologies are merely functional. These actually use a custom control template library to make the samples look less generic. The control templates are out of the way in the samples, so it is still easy to focus on the functionality when reviewing the XAML.

Full Coverage of Silverlight 2 Data Access
Finally, since this book is focused simply on data access, it can cover a variety of data sources and methodologies. Chapters 1-4 are overviews of the technologies used in data access in Silverlight. Chapters 5-11 cover specific data sources. Here's a breakdown of the book chapter by chapter:

  1. Getting Started with Silverlight 2
    A few Silverlight 2 basics (such as Data Services and the Control Model) and .NET topics (such as LINQ and C# language enhancements) which are needed in later topics such as data binding.
  2. Silverlight Data-Binding Foundation
    The data-binding basics including dependency properties, XAML binding markup, and the DataContext.
  3. Modes and Notifications
    OneTime, OneWay, and TwoWay binding modes and the INotifyPropertyChangedInterface.
  4. Managing Lists, Templates, and Converters
    An overview of working with list-based controls, implementing data templates, and building value converters.
  5. WCF, Web Services, and Cross-Domain Policies
    How to build and call ASMX services, and also using WCF services that are compatible with Silverlight 2.
  6. Passing Entities via WCF
    How to send entities (simple classes) back and forth using LINQ to SQL and Entity Framework.
  7. Consuming RESTful Services with WebClient and HttpWebRequest
    An introduction to REST and using WebClient (simpler) or HttpWebRequest (more complex, but more flexible) to interact with RESTful services.
  8. Consuming Amazon's RESTful Services with Silverlight 2
    A specific example interacting with Amazon to search items, create a shopping cart, and add items to that cart.
  9. Creating RESTful Services and Introducing SilverTwit
    More REST, including consuming JSON services. The SilverTwit sample uses a series of services to create a Twitter client in Silverlight.
  10. Syndication Feeds and Silverlight 2
    How to interact with RSS and Atom feeds.
  11. Silverlight 2 and ADO.NET Data Services
    An overview of ADO.NET Data Services and how to interact with them with Silverlight.

Summary
If you create data-centric applications and are working with Silverlight 2, you need this book. By the time I got to the end of this book, I was extremely comfortable creating services and consuming them with Silverlight. This is an excellent addition to my collection of reference books, and I am finding myself repeatedly opening up the sample applications to review different data access techniques. I am very glad that I came across this excellent resource.

I read between 8 and 10 technical books per year (generally in the 500 to 900 page range). I find the majority of them useful, but occasionally one will jump out as being particularly relevant. That is how I felt with Data-Driven Services with Silverlight 2.

Saturday, April 4, 2009

Getting Started with Silverlight 2

I was planning on doing my next application at work in WPF, but it turned out that Silverlight 2 was a better fit. So, I've been doing some quick and dirty work to get up to speed. The good news is that the UI model with XAML is pretty similar (I'll let others get into the specific differences). The bad news is that everything happens asynchronously. Okay, so that's not really bad news, it's just something to get used to. I'll be covering some of my specific learnings on asynchronous programming a bit later, so stay tuned.

Database Programming
As I said earlier, I write business applications for a living. And that means database access. Silverlight does not support direct database access (such as ADO.NET or LINQ to SQL), so that means that everything happens through network calls. WCF is the best choice for this (with some limitations).

It took me a while to get comfortable with this concept. The best introductory resource that I found is actually on the silverlight.net site, including very useful tutorial videos. The most helpful one for me was #58 "How to Consume WCF and ASP.NET Web Services in Silverlight" by Tim Heuer. It's about 23 minutes and definitely worth the time.

Here's the short version:
  1. Create a WCF Service using basicHttpBinding (Silverlight 2 only supports this binding).
  2. Generate a proxy class for the service in the Silverlight application using the standard Add Service Reference.
  3. Create an instance of the proxy.
  4. Hook up a call-back by assigning a handler to [methodName]Completed. Visual Studio is good at helping create the stubs for you (see the video for a demo).
  5. Call the [methodName]Async() to kick off the call.
Resources
If your applications are data centric, then you will definitely want to check out John Papa's book: Data-Driven Services with Silverlight 2 -- with an introduction by Tim Heuer. This book is all about data access, whether you are creating your own services or consuming existing services. This is a relatively short book (at about 350 pages -- small for a tech book), but the text and samples (easily available for download) are very good. By the time that I got to the end, I was so comfortable with consuming services with Silverlight and working with the asynchronous calls that I could code them up with my eyes closed. I'm planning on doing a full review of this book in a later post.

The official Microsoft site has a lot to offer. In addition to the video mentioned above, there are lots more on all different topics. Just check out http://silverlight.net/Learn/.

I mentioned the Matthew MacDonald WPF book in a previous post. The good news is that there is a sibling Silverlight book: Pro Silverlight 2 in C# 2008. This is a very good overview of Silverlight 2 including XAML basics, layout, controls, animation, styles/templates, service calls, and browser integration. The accompanying samples are also very good and cover all of the included topics.

I always point to dnrTV for good web-casts. You can check out episode #127: Shawn Wildermuth on Silverlight 2 Data. Lots of interesting tidbits scattered throughout.

My Experience So Far...
Silverlight 2 is an adventure. It's not quite web programming, and it's not quite WinForms programming. It sits squarely between the two. More details coming up...

Monday, March 9, 2009

Target Practice - WPF / XAML Sample

This time we'll be looking at a few of the points from my last post: What I Like About WPF. I set out to create a short demo that uses only XAML (with no code behind) to show the power of some of the features; specifically declarative programming, templates, styles and "lookless" controls. So, let's get to the scenario.

[Editor's Note 06/2013: This example is simply some cool stuff about XAML.  If you want to see a more complete example of a button control template (including a ContentPresenter), please refer to Metrocizing XAML: Part 2 - Control Templates.]

Scenario
We'll be creating a very simple shooting gallery-type application. I call it "Target Practice" since it will require some more work to turn it into an actual game. In the final version, we will have a 3 x 3 grid of targets. Each of these is clickable and will result in a "hit" animation. After 3 seconds, the target will reset to its previous state -- all inside the XAML. You can scroll down to the bottom to see the finished product.

Source code for this sample is available here: http://www.jeremybytes.com/Downloads.aspx#TPW.

Step 1 - Application Set-up
We'll start by creating a new WPF application. I'm using Visual Studio 2008, but everything I'm doing here should work in 2005 as well. Create a new project by selecting File -> New -> Project. From there, choose the "Windows" category under "Visual C#" and select "WPF Application".

In the new application, you will find a "Window1.xaml" file. That's where we are going to start. Open up the xaml file, and you will see a designer and xaml editor. We'll be focusing on the xaml editor. Here's what the project template creates:

(Click images to enlarge)


We're going to make a few changes. Again, this isn't a tutorial on XAML, we're just focusing on showing some of the power. Resources from the previous post are helpful if you are completely new to XAML. First thing we'll do is change a few properties in the "Window" tag. Set the following properties:

Title="Target Practice"
Height="370"
Width="350"

Next, we'll replace the Grid with a set of nested StackPanels. The nested StackPanels will set up our 3 x 3 grid (I could have used the Grid here as well, but the StackPanels are better at letting things "flow"). Inside each nested StackPanel, I have placed 3 buttons. The StackPanel code (that replaces the Grid) looks like this:



When you run the application, you will get a highly exciting result that looks like this:



Step 2 - Templates & Styles
So, we have a grid of buttons; now what? Next, we are going to take advantage of the "lookless" controls. WPF controls do not have any inherent visual styling to them. They simply use a default template that is provided by the framework. We are going to replace that template with our own to create a custom button. And hopefully, by the time we get done, you'll see how much easier this is to do in WPF than it is in other UI technologies.

We're going to add a local resource to the file. Add a tag "Window.Resources" just above the outer StackPanel. You'll find that Visual Studio IntelliSense is very helpful when hand-editing XAML. There are visual ways of doing this with Expression Blend, but that's another topic. Inside the Resources section, we'll add a ControlTemplate.



A few key things to point out. The TargetType is set to Button. This means that we can apply this template to button controls (and only to buttons). Next is x:Key: this gives a name to the template that we can use elsewhere. Next we have a Canvas (basically our drawing surface) and an Ellipse (which is just a DarkRed circle). Note: this is called the "Outer Red Stripe" in the comments because we will be adding more to this later on.

From here we are going to add a Style. The reason for adding a Style will become apparent as we move along. For now, you can see that we create a new Style, give it some Margins, and then set the Template property to our ControlTemplate:



Styles work by using Setters. The Setters let you select a property (such as Template) and then assign a value to it. You'll notice the syntax for the Template setter looks like this: Value="{StaticResource targetButton}". The curly braces denote that we aren't setting the value directly; we are binding to another object, in this case a StaticResource. The "targetButton" is the x:Key that we specified on our ControlTemplate above.

One thing to note on our Style: we would normally use an x:Key here as well, which would give us a named style that we can apply in our UI. Styles have the special behavior that if you exclude the x:Key, then the style will automatically be applied to every control in that scope. In this case, since the TargetType is Button, it will be applied to every button in our Window. Here's what our application looks like now.



One thing to note: the red circles are still buttons. They are clickable (although they don't visually change when you click on them), and they have standard button events (such as Click). Notice that they do not have any content (Button1a, Button1b, etc.). This is because our template does not contain an element for the Content. If you are creating your own buttons, then you will want to look at this and other behaviors (such as having different visuals for up, down, and hover). So far the visuals for our application aren't that great. Step 3 is going to change that.

Step 3 - Eye Candy
Now we'll take our boring red circles and make them into glassy 3-D buttons. The best way to learn how to do this is to take a look at some Photoshop tutorials and use the same techniques in Expression Blend. The cool part about using Blend is that when you have what you want, you can simply copy the XAML (or have it included as a resource in your project). I am not a graphic designer, and I will admit to stealing this "top glow" and "bottom glow" sections from a demo by Walt Ritscher. He is also a good resource for WPF styles and templates.

First, the top glow. This is simply added to our ControlTemplate below the DarkRed Ellipse. All it is is an ellipse with a radial gradient that moves from white to transparent.



The bottom glow is much the same: just an ellipse with a radial gradient.



What you see when you run the application is a distinct difference in what we had before:



Pretty cool, eh?

Step 4 - Completing the Targets
Next, we just need to complete the visual design of our Targets. This is just a set of ellipses, each smaller than the last, alternating Red and White.



A few things to note here. You'll see that we are moving the Canvas.Left and Canvas.Top properties because the Top Left corner is considered the starting point for drawing. We are moving down a bit and to the right to make a smaller circle on top of the previous one.

Order is important here. The XAML parser processes items in the order that they appear in the file. This means that the "Outer Red Stripe" (our first circle) needs to be specified first, and then as each smaller circle is defined, the XAML parser layers it on top of the last. If we were to reverse the order, then the large circle would simply cover everything underneath it. The same is true for the "glows." We want those as the top layer, so we specify them last in the XAML.

On a side note: Silverlight has a Canvas.ZIndex property that allows you to explicitly set the order of the layering. This is not available in the current version of WPF, but we'll see what the future holds when .NET 4.0 comes out later this year.

When we're done, our targets will look like this:



Step 5 - The Action
The last step is to add the behavior. As a reminder, when we click on a Target, we want it to animate to fall over, and then reset after 3 seconds. The animation will work by using a Transform. The first step is to define an empty Transform in our Style (note: we are adding this to the Style, not the ControlTemplate).



Next, we will add a Trigger to our Style. A Trigger denotes a change to a style based on some external influence. In our case it will be a response to a Button.Click, but it could be a MouseOver or other event.



This is a big bit of code, so let's walk through it. First, we are setting up a Triggers section in our Style. Next we are setting up a EventTrigger on the "Button.Click" RoutedEvent. Inside the EventTrigger, we have an Action section which will contain our actual animation. The EventTrigger and corresponding animation is why we need to use a Style here (as opposed to using just the ControlTemplate).

The animation is declared with Storyboards. This is another section where using Expression Blend is helpful. You can define an animation using visual tools, and then copy the XAML back into your application (or use it directly as a Resource).

The first "DoubleAnimation" on "RenderTansform.ScaleY" means that we will be changing the "Y" scale (meaning the Height) over the duration specified (0.3 seconds) and changing it from 1 (full height) to 0.01 (which ends up looking like a line on the screen). If we were to use this animation by itself, then our button would actually shrink "up" because the origin is at the top left corner. In order to get it to shrink "down", we need to add another transform.

The second "DoubleAnimation" on "RenderTransform.CenterY" means that we will be moving the origin of our button. This time from 0 (the top) to 110 (which is actually a little bit below the bottom of our 100 unit Canvas -- the Canvas is a special container in that you can actually draw outside of its boundaries).

Let's take a step back for a moment and talk about animation. What you will notice is that we do not have any timers specified here. To perform this animation in the WinForms world, we would use a timer, and then perform some action on every tick (such as moving an image a few pixels). Animation in XAML is declarative. This means that we tell it what we want to do (move from here to there and take 0.3 seconds to do it) and not how to do it (move 3 pixels each 100 milliseconds). The animation declaration itself is just changing a Property on the element. In this case, we are making changes to the empty RenderTransform that we defined earlier. The "DoubleAnimation" denotes that we are changing a Property that is of type Double (specifically the RenderTransfor.ScaleY and RenderTransform.CenterY).

These two animations together will result in our Target being "hit" and falling down.

The next 2 "DoubleAnimations" are basically doing the opposite. Note that these both have a BeginTime of "0:0:3", which means that this section of the animation will start after 3 seconds have elapsed. This will return our Target to the upright position after 3 seconds.

You'll have to run it yourself to see the final result. Here's a screen shot of things in action:



Round Up
So, what we've seen here is a pretty impressive application for not having any C# code. In fact, we could have started with a VB project and come up with exactly the same results. We were able to declaratively program the behavior using XAML only -- and all in less than 120 lines. We took advantage of the lookless controls by replacing the default template and style with our own. With a little bit of C# code, we could turn this into a full fledged Shooting Gallery. But I'll leave that to you.

Happy coding!

Sunday, March 1, 2009

What I Like About WPF

Windows Presentation Foundation (WPF) is the future of Rich Client (or Smart Client or Fat Client or whatever term is in fashion) programming in .NET. Microsoft is using WPF for the UI in Visual Studio 2010. If you are like me, then you still haven't had a chance to work with it extensively (due to constraints of my day-job). But, if you are like me, you are also very excited about the technology -- and not just because of the eye candy (although that is an added bonus; albeit a potentially dangerous one).

Note: this isn't an introduction to WPF. I have some resources listed below if you want more info. So, here's what I like...

Declarative Programming Model
You can do quite a bit of the UI work in the XAML itself (XAML stands for eXtensible Application Markup Lanuage -- for more information, look for an intro to XAML). This UI work includes triggers, animations, and data bindings. Sure, you can do the work in your C# (or VB) code, but it's nice to be able to put it into the XAML.

Data Binding
I write business applications for a living -- that means pretty much everything requires some sort of data access. There are several WPF data binding features that seem to combine the best of WinForms data binding and ASP.NET WebForms data binding, plus some new features thrown in.

Binding to the container
Since you can bind the DataContext (your data source) to a UI container (which is pretty much everything -- see below), every child element can use that DataContext implicitly.

Good Support for value converters
IValueConverter is nothing new, but I have seen several WPF demos that use it in the data binding, making things dead simple. For example, you can use a value converter to convert a bank balance (an integer) to a brush (red for negative values, black for positive). In your bindings, you can bind the Brush on a TextBox directly to the bank balance, and the value converter takes care of the rest.

Binding to static resources
You can use data binding syntax to connect properties to static resources that are either defined locally to the page or globally to the application. As a programmer, you need to do less internal context switching since the syntax is the same regardless of whether you are binding to a static resource or a dynamic data context.

Binding from one element property to another
I'm not sure why I like this so much, but for some reason I do. If you need to display the same data twice on a page (like in a master / detail or selection / detail relationship), you can bind the Content property of one element ot the Content property (or any other property) of another.

Commands
Coming from the Delphi programming world, I always wondered where the concept of Actions went in C# (after all, Anders Heilsberg was the architect of both languages). Commands allow you to hook up several UI elements to the same command. For example, you can hook up a menu item, tool bar item, and a button to a single Command (such as Save). This lets you enable or disable the Command, and it will affect all connected UI elements. (Also, you have centralized code which is always good.)

Now let's move on to some more visual features. (I'm skipping the eye-candy at this point to focus on usability.)

Most controls are also containers
This adds immense flexibility to the UI designer. You have full control over layout of a button that has both an image and text. Anyone who has fought with the layout of an image button in WinForms will greatly appreciate this.

Flexible layout and resolution independence
If you pay attention to your layout, you can design an UI that is usable on both a 23" desktop monitor and a 9" netbook. This will seem somewhat familiar to web developers. Plus, if you focus on using vector graphics (as opposed to bitmaps), then you can get good scaling without aliasing (i.e. "jaggies").

Templates and styles
This seems very comfortable to web developers who use CSS. But it is incredibly more powerful. I'll be focusing on this in a future post.

"Lookless" controls
None of the WPF UI controls have a built in rendering. Instead, they have default templates. This means you can replace the default with your own template to make a control appear however you want. Because the base control is "lookless", it means that all of the functionality (such as "Click" on a button) is separated from the rendering; so, you can replace the visual rendering without impacting the underlying functionality.

Lack of a DataGrid
This one may sound weird. Most of the WPF forums are littered with developers complaining about the lack of a data grid. There is even a CodePlex project to implement one. But I have found the lack of a DataGrid to be an opportunity.

In my applications, I generally use data grids because they are easy -- not because they are the best way to present the information to the user. I have started to think about the power of the ListView. By using containers and templates (including data templates), I have full control over how I present the data, and it's dead simple.

"Dead simple" is the key. Most of the things that I've mentioned are possible to do in WinForms, but you end up jumping through hoops to accomplish them. WPF makes these things "dead simple." If you're curious about alternatives to displaying data (without a Data Grid), then check out some of Billy Hollis' web casts (see below for links).

So, that's why I am excited about WPF. If you are, too, then you can check out these resources:

The Official Microsoft WPF and Windows Forms Site
This site is loaded with tutorials, samples, downloads, and lots of info.

dnrTV
This site has web casts (generally about an hour long) on all sorts of .NET topics. As mentioned above, Billy Hollis has done some excellent episodes:
dnrTV - Episode 115 - Billy Hollis: Getting Smart with WPF
dnrTV - Episode 128 - Billy Hollis: XAML for Developers Part 1
dnrTV - Episode 129 - Billy Hollis: XAML for Developers Part 2

Pro WPF in C# 2008: Windows Presentation Foundation with .NET 3.5, Second Edition - Matthew MacDonald
This is an excellent (large) book. It's around 1000 pages, and has lots of great information and samples. There is also a VB version of this book if that is your language of choice.

I'll be digging in to specific WPF topics as time goes on, so stay tuned!