Project Turing: Beginning RIA Services

Reposted with VB.Net code

From Database to DataGrid

The next step in Project Turing is to create a first iteration of the Silverlight application that will retrieve data from our database.  Using our technology of choice: the Data Entity Framework coupled with .Net RIA Services.

.Net RIA Services will allow us to create business logic on the server and to access that same set of classes on the client.  We will retrieve the data from these business classes and display them in a data grid within a business application, that is a multipage Silverlight application.

.NET RIA Services

While a great deal has been written about RIA Services, I find when talking with Silverlight developers that there is still some confusion about where RIA Services are best used and what the key benefits are.  This really  isn’t terribly surprising given how new the RIA Services platform is. Despite the incredible work done by Brad Abrams and others on the dev team  to document RIA Services,  it will take a while for many Silverlight programmers to fully integrate the platform into their designs

Project Turing offers an ideal opportunity to provide an incremental introduction to  RIA Services and an illustration of the immediate benefits of the platform.

Just before the progress took the digression into Linq, we created our basic database tables, and the initial architecture of Project Turing. Here is a snapshot of the database as it exists at this point in the project:

DataBaseDesign
(click on image for full size)

Our goal now is to retrieve this data using the Data Entity Framework and to make it available to the DataGrid using .NET RIA Services.

What You Need To Program With RIA Services Project

For this part of Project Turing you’re going you need to install the latest .Net RIA Services framework.  You can find complete instructions and all of the libraries that you need here. (There is no cost.)

You also want to create or download the Turing database, which you can install to SQL Server 2005, SQL Server 2008, or SQL express.  You can download a backup of this database and restore it to your system, from here.  Alternatively you can download a script to re-create the database from here.

Getting Started

We will build the application incrementally, starting with a simple version and adding complexity as we go.  Specifically, we will break down the steps of interacting with the database into a series of smaller tasks.

The goal in this first example will be to create a shell of a multipage application, and within that a page to which we’ll add a basic  DataGrid. To get started open Visual Studio and create a new project. In the Project Type, select Visual C#/Silverlight, and in the templates select Silverlight Business Application.  I named my project TuringRIAServices.

Creating Business App
(Click image for full size)

A fairly sophisticated Silverlight application is created for you out-of-the-box.  Your solution consists of two projects, and your Xaml project has three subdirectories: Assets, Libs, and Views.

The views folder contains the initial pages already provided in the application.  These include Xaml files for logging in, a Home page, a custom error window and an about box.

MainPage.xaml acts as a shell and a dispatcher to the pages that are in the Views folder.  The Assets folder contains your first styles Xaml page, but you are free to add more (as you are to all the folders).

To begin open MainPage.xaml and let’s examine some of what has been put in place by Visual Studio.

<Grid x:Name="LayoutRoot" Style="{StaticResource LayoutRootGridStyle}">
<Border x:Name="ContentBorder" Style="{StaticResource ContentBorderStyle}">
           <navigation:Frame x:Name="ContentFrame" Style="{StaticResource ContentFrameStyle}"
                             Source="/Home" Navigated="ContentFrame_Navigated" NavigationFailed="ContentFrame_NavigationFailed">
                <navigation:Frame.UriMapper>
                  <uriMapper:UriMapper>
                    <uriMapper:UriMapping Uri="" MappedUri="/Views/Home.xaml"/>
                     <uriMapper:UriMapping Uri="/{pageName}" MappedUri="/Views/{pageName}.xaml"/>
                   </uriMapper:UriMapper>
                 </navigation:Frame.UriMapper>
             </navigation:Frame>
     </Border>

     <Grid Style="{StaticResource NavigationOuterGridStyle}">
       <Grid x:Name="NavigationGrid" Style="{StaticResource NavigationGridStyle}">

        <Border x:Name="BrandingBorder" Style="{StaticResource BrandingBorderStyle}">
        <StackPanel x:Name="BrandingStackPanel" Style="{StaticResource BrandingStackPanelStyle}">

             <ContentControl Style="{StaticResource LogoIcon}"/>
             <TextBlock x:Name="ApplicationNameTextBlock" Style="{StaticResource ApplicationNameStyle}"
                               Text="Application Name"/>

          </StackPanel>
        </Border>

        <Border x:Name="LinksBorder" Style="{StaticResource LinksBorderStyle}">
          <StackPanel x:Name="LinksStackPanel" Style="{StaticResource LinksStackPanelStyle}">

<HyperlinkButton x:Name="Link1" Style="{StaticResource LinkStyle}"
                                  NavigateUri="/Home" TargetName="ContentFrame" Content="home"/>

           <Rectangle x:Name="Divider1" Style="{StaticResource DividerStyle}"/>

            <HyperlinkButton x:Name="Link2" Style="{StaticResource LinkStyle}"
                                     NavigateUri="/About" TargetName="ContentFrame" Content="about"/>

           </StackPanel>
         </Border>

       </Grid>

       <Border x:Name="loginContainer" Style="{StaticResource LoginContainerStyle}"/>
    </Grid>

  </Grid>

Before taking this apart lets look at what is created if you build and run this without making any changes.

Running Out of the box

(Click image for full size)

You can see in the image that there is a frame around the home page, which has within it a logo, the name of the application, a button for the currently selected page, a button for the about page, and a small button for the login dialog.

This corresponds directly of course to the Xaml above.

On line 2, we  create a border, which uses the static resource predefined by Visual Studio and stored in  Styles.Xaml within the Assets folder.

Within that border a Frame object is defined on line 3 through 11, within the navigation namespace defined at the top of the file.

xmlns:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation"

The frame has three critical properties:

  • The source.
  • The name of the method to call after successfully navigating to the page.
  • The name of the method to call in the event of failure.

Nested within the frame is a mapper, whose job is to map pages to URIs.

Note on line 8, the generic mapping that is used with the substitution parameter pagename.  This is a subtle but very powerful capability that allows you to create essentially a template of the relationship between pages in their URI and avoid duplicating this code for every page.

The second major UI area within this Xaml file begins on lines 14 and 15 with the creation of an outer and inner grid.

The content control defined on line 20 is used to display the logo and on line 21 is a standard textblock, where the text is set to Application Name.  This would be a good opportunity to change that text to “Project Turing RIA Services”

The second area is itself divided in to two areas each with its own water, and in the lower area beginning on line 27.  Line 30 shows the hyperlink button for the homepage and on line 35 is the hyperlink button for the about page.  Adding a new button only requires an additional hyperlink button.  In this section, the navigation is handled by the section about.

You may find it worthwhile and interesting to open up the style.xaml  file, and take a look at the static resources that were created by this template.

Adding A DataGrid

We will add the Silverlight control DataGrid to a new Silverlight page.  To do so, right-click on the project and choose Add –> New Item.  In the Add Item dialog box, choose Silverlight under categories and Silverlight Page in the templates pane.

Name the new page BlogsDataGrid and click Add.

At the top of this page, we will place a header as we will on each new page.  The header consistents of a  ScrollViewer, within which we will place a StackPanel, within which we will place a Toolbox with the name of the page as shown here:

Note: this design, and much in these examples, comes from the Walk-Through created by the development team and used here with their permission, for which I and my Carpal Tunnel Syndrome are very grateful.

<ScrollViewer BorderThickness="0"

              VerticalScrollBarVisibility="Auto"

              Padding="12,0,12,0"

              Margin="-12">

    <StackPanel Margin="0,12,0,12"

                Orientation="Vertical">

        <TextBlock Text="Blogs"

                   Style="{StaticResource HeaderTextStyle}" />

    </StackPanel>

</ScrollViewer>

Finally, drag a DataGrid from the toolbox into the grid.

Note: the advantage of dragging from the toolbox rather than writing the Xaml by hand is that Visual Studio will create the necessary namespace and use that as a prefix for the DataGrid
xmlns:data="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data"

Once Visual Studio has fixed up the namespace, modify the data grid element to include the properties Name (BlogsDataGrid), MinHeight (150), and IsReadOnly (true).

<navigation:Page

  xmlns:data="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data"

  x:Class="TuringRiaServices.Blogs"

  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

  xmlns:d="http://schemas.microsoft.com/expression/blend/2008"

  xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"

  xmlns:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation"

  mc:Ignorable="d"

  d:DesignWidth="640"

  d:DesignHeight="480"

  Title="Blogs Page">

    <Grid x:Name="LayoutRoot">

        <ScrollViewer BorderThickness="0"

                      VerticalScrollBarVisibility="Auto"

                      Padding="12,0,12,0"

                      Margin="-12">

            <StackPanel Margin="0,12,0,12"

                        Orientation="Vertical">

                <TextBlock Text="Blogs"

                           Style="{StaticResource HeaderTextStyle}" />

            </StackPanel>

        </ScrollViewer>

        <data:DataGrid x:Name="blogsDataGrid"

                       MinHeight="150"

                       IsReadOnly="True"></data:DataGrid>

    </Grid>

</navigation:Page>

Your page is ready, but there is no way to navigate to it.  Return to MainPage.Xaml and let’s add the logic for an additional button.

First, take a look at the solution Explorer, and if BlogsDataGrid.Xaml is not in the views folder   drag it there now.

As noted above, all we need to do here is add a hyperlink button for our new page.  This will go immediately below the hyperlink button for the about box

<HyperlinkButton x:Name="Link3"

                 Style="{StaticResource LinkStyle}"

                 NavigateUri="/Blogs"

                 TargetName="ContentFrame"

                 Content="Blogs" />

Build and run the application and be sure to click on the new button for the Blogs page. Please take note of the very elegant handling of the exception that is thrown, because we wired up for a same blogs.  But our actual page is named BlogsDataGrid.

While we’re fixing that link, lets take note of the fact that Visual Studio has named each of the hyperlink buttons.  Link one, link two etc. , while it is natural and common to continue this as we have done above, I greatly prefer to name the hyperlink buttons to indicate their function.  And so I will rename Link1  HomeLinkButton; Link2  AboutLinkButton and our Link3 BlogsLinkButton. I will also fix up the NavigateURI to the full name of the page.

One defensible choice is to continue the pattern provided by Visual Studio, but it is my personal approach to rename all three on the premise that good naming practice makes for good documentation.

<UserControl x:Class="TuringRIA_Services.MainPage"     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"     xmlns:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation"     xmlns:uriMapper="clr-namespace:System.Windows.Navigation;assembly=System.Windows.Controls.Navigation"     xmlns:dataControls="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data.DataForm.Toolkit"     xmlns:d="http://schemas.microsoft.com/expression/blend/2008"     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"     mc:Ignorable="d"     d:DesignWidth="640"     d:DesignHeight="480">   <Grid x:Name="LayoutRoot"         Style="{StaticResource LayoutRootGridStyle}">      <Border x:Name="ContentBorder"              Style="{StaticResource ContentBorderStyle}">         <navigation:Frame x:Name="ContentFrame"                           Style="{StaticResource ContentFrameStyle}"                           Source="/Home"                           Navigated="ContentFrame_Navigated"                           NavigationFailed="ContentFrame_NavigationFailed">            <navigation:Frame.UriMapper>               <uriMapper:UriMapper>                  <uriMapper:UriMapping Uri=""                                        MappedUri="/Views/Home.xaml" />                  <uriMapper:UriMapping Uri="/{pageName}"                                        MappedUri="/Views/{pageName}.xaml" />               </uriMapper:UriMapper>            </navigation:Frame.UriMapper>         </navigation:Frame>      </Border>      <Grid Style="{StaticResource NavigationOuterGridStyle}">         <Grid x:Name="NavigationGrid"               Style="{StaticResource NavigationGridStyle}">            <Border x:Name="BrandingBorder"                    Style="{StaticResource BrandingBorderStyle}">               <StackPanel x:Name="BrandingStackPanel"                           Style="{StaticResource BrandingStackPanelStyle}">                  <ContentControl Style="{StaticResource LogoIcon}" />                  <TextBlock x:Name="ApplicationNameTextBlock"                             Style="{StaticResource ApplicationNameStyle}"                             Text="Project Turing RIA Services" />               </StackPanel>            </Border>            <Border x:Name="LinksBorder"                    Style="{StaticResource LinksBorderStyle}">               <StackPanel x:Name="LinksStackPanel"                           Style="{StaticResource LinksStackPanelStyle}">                  <HyperlinkButton x:Name="HomeLinkButton"                                   Style="{StaticResource LinkStyle}"                                   NavigateUri="/Home"                                   TargetName="ContentFrame"                                   Content="home" />                  <Rectangle x:Name="Divider1"                             Style="{StaticResource DividerStyle}" />                  <HyperlinkButton x:Name="AboutLinkButton"                                   Style="{StaticResource LinkStyle}"                                   NavigateUri="/About"                                   TargetName="ContentFrame"                                   Content="about" />                  <HyperlinkButton x:Name="BlogsLinkButton"                                   Style="{StaticResource LinkStyle}"                                   NavigateUri="/BlogsDataGrid"                                   TargetName="ContentFrame"                                   Content="Blogs" />               </StackPanel>            </Border>         </Grid>         <Border x:Name="loginContainer"                 Style="{StaticResource LoginContainerStyle}" />      </Grid>   </Grid></UserControl>

This time clicking on the blogs hyperlink does not throw an exception but rather brings you to the blogs page, where the outline of the DataGrid is drawn but of course there is as of yet no data.  Let’s fix that now.

Adding Business Logic And Data

Our next principal task is to retrieve data from the database and present it to the DataGrid.  As noted in previous mini tutorials and postings for this project, there are a number options for retrieving data from a database.  One of the most powerful is to use the Entity Framework.

When a developer says technology is “powerful,” we typically mean that it does a lot of the routine plumbing for us, and that it is highly flexible.  Certainly both are true of the Entity Framework.

A quick look at Julia Lerman’s Programming Entity Framework (O’Reilly Media, 2009) is both reassuring and somewhat intimidating; her book is over 750 pages.  This stands as testimony to the enormous flexibility of the Entity Framework.

That said, using the Entity Framework to retrieve data from a relatively straightforward relational database can be explained quite quickly. I will demonstrate enough of the Entity Framework to get a feel for the role that it plays and the level of abstraction that it provides, but in no way will this be a comprehensive survey of the Entity Framework in its entirety.

To begin, add a new item to Turing RIA Services.web.  In the Add New Item dialog select Data in the Categories pane, and choose ADO.net Entity Data Model in the templates pane, and name the new Entity Data Model TuringBlogs.  Indicate to the Entity Data Model Wizard that you wish to generate your model from an existing database.

Adding Entity Data Model

(Click image for full size)

You’ll be prompted to create or reuse a connection string for your database

CreateDataConnection

(Click image for full size)

Note that using the second radio button “include the sensitive data in the connection string,”  will slightly simplify your code, but expose a significant security hole.

After connecting to your database, you’ll be asked to choose which objects you wish to include.  Expand the tables, and select the Blogs table.

SelectBlogsTable

(Click image for full size)

When you click finish, the entity data model will appear in the designer. To verify that everything is correct, build the solution.

Transporting the Data Class To The Client With .Net RIA Services

You’re halfway home.  You now have an entity (object) that represents the data that is stored in relational tables in SQL Server.  The next step is to create business classes that will represent and manipulate that data on the server, and be equally available on the client.  That is in a nutshell, what.net RIA Services does for a living.

Once again right-click on the Turing RIA Services Web project, and add a new item. However this time, in the Categories pane, select Web and in the templates pane Domain Service Class.  Name the new item BlogsService and click Add.

AddingBlogService

(Click image for full size)

Click Add which will open the Add New Domain Service Class dialog. Select Blogs from the list of entities (okay, in this case it’s the only item in the list).  In the same dialog, be sure to check Enable Editing, which enables the CRUD functionality, and at the bottom of the dialog, click “Generate associated classes for metadata.” Then click OK.

NewDomainServiceClassDialog

(Click image for full size)

Open the class of this generates for you: BlogsService.cs and modifying the GetBlogs method as follows:

C#

//Replace this generated code:
public IQueryable GetBlogs()
{
   return this.Context.Blogs;
}

// with this custom code:
public IQueryable GetBlogs()
{
  return this.Context.Blogs.OrderBy(b => b.BlogName);
}

VB.Net

'Replace this generated code:
Public Function GetBlogs() As IQueryable(Of Blogs)
   Return Me.Context.Blogs
End Function

' with this custom code:
Public Function GetBlogs() As IQueryable(Of Blogs)
  Return Me.Context.Blogs.OrderBy(Function(b) b.BlogName)
End Function

In this first example, our customization is ordering the results by the name of the blog.

Define It on the Server, Invoke It on the Client

When you rebuild the solution not only will the classes that you’ve created in the server be built, but a corresponding set of proxy classes will be built in the client project.

Thus the class and its method will be available on the client side, and therefore available to our DataGrid.  At the top of the code behind page will need to add three using statements; one to bring in the web project, and the other two for RIA Services:

C#

using TuringRIAServices.Web;
using System.Windows.Ria.Data;
using System.Windows.Ria.ApplicationServices;

VB.Net

Imports TuringRIAServices.Web
Imports System.Windows.Ria.Data
Imports System.Windows.Ria.ApplicationServices

In the generated code in the client project, the BlogsContext is generated based on the BlogsService you created on the server. To see the definition, turn on show all files, and locate the file TuringRIAServices.web.g.cs / TuringRIAServices.web.g.vb. Inside the previously hidden Generated_Code folder. In that file, you will find the definition for the BlogsContext.

C#

public sealed partial class BlogsContext : DomainContext
{
    partial void OnCreated();

    public BlogsContext() :
            this(new HttpDomainClient(
              new Uri("DataService.axd/TuringRIA_Services-Web-BlogsService/", System.UriKind.Relative))) {}

   public BlogsContext(Uri serviceUri) :
            this(new HttpDomainClient(serviceUri)) {}

    public BlogsContext(DomainClient domainClient) :
            base(domainClient)
    { this.OnCreated(); }

    public EntityList Blogs
    {
        get { return base.Entities.GetEntityList();  }
    }

    public EntityQuery GetBlogsQuery()
    {
        return base.CreateQuery("GetBlogs", null, false, true);
    }

    protected override EntityContainer CreateEntityContainer()
    {
        return new BlogsContextEntityContainer();
    }

    internal sealed class BlogsContextEntityContainer : EntityContainer
    {

        public BlogsContextEntityContainer()
        {
            this.CreateEntityList(EntityListOperations.All);
        }
    }
}

VB.Net

Public NotInheritable Partial Class BlogsContext
	Inherits DomainContext
	Partial Private Sub OnCreated()
	End Sub

	Public Sub New()
		Me.New(New HttpDomainClient(New Uri("DataService.axd/TuringRIA_Services-Web-BlogsService/", System.UriKind.Relative)))
	End Sub

   Public Sub New(ByVal serviceUri As Uri)
	   Me.New(New HttpDomainClient(serviceUri))
   End Sub

	Public Sub New(ByVal domainClient As DomainClient)
		MyBase.New(domainClient)
	Me.OnCreated()
	End Sub

	Public ReadOnly Property Blogs() As EntityList(Of Blogs)
		Get
			Return MyBase.Entities.GetEntityList(Of Blogs)()
		End Get
	End Property

	Public Function GetBlogsQuery() As EntityQuery(Of Blogs)
		Return MyBase.CreateQuery(Of Blogs)("GetBlogs", Nothing, False, True)
	End Function

	Protected Overrides Function CreateEntityContainer() As EntityContainer
		Return New BlogsContextEntityContainer()
	End Function

	Friend NotInheritable Class BlogsContextEntityContainer
		Inherits EntityContainer

		Public Sub New()
			Me.CreateEntityList(Of Blogs)(EntityListOperations.All)
		End Sub
	End Class
End Class

Returning to BlogsDataGrid.xaml.cs, instantiate a BlogsContext as a member variable,

C#

private BlogsContext blogsContext = new BlogsContext();

VB.Net

Private blogsContext As New BlogsContext()

Here is the complete BlogsDataGrid.xaml.cs / BlogsDataGrid.xaml.vb

C#

private BlogsContext blogsContext = new BlogsContext();

VB.Net

Private blogsContext As New BlogsContext()

Here is the complete BlogsDataGrid.xaml.cs (BlogsDataGrid.xaml.vb in case of VB.Net):

C#

using System.Windows.Controls;
using System.Windows.Navigation;
using TuringRIA_Services.Web;
using System.Windows.Ria.Data;
using System.Windows.Ria.ApplicationServices;

namespace TuringRIA_Services
{
   public partial class BlogsDataGrid : Page
   {
      private BlogsContext blogsContext = new BlogsContext();

      public BlogsDataGrid()
      {
         InitializeComponent();
         this.blogsDataGrid.ItemsSource = blogsContext.Blogs;
         blogsContext.Load( blogsContext.GetBlogsQuery() );
      }

      protected override void OnNavigatedTo( NavigationEventArgs e )
      {
      }
   }
}

VB.Net

Imports System.Windows.Controls
Imports System.Windows.Navigation
Imports TuringRIA_Services.Web
Imports System.Windows.Ria.Data
Imports System.Windows.Ria.ApplicationServices

Namespace TuringRIA_Services
   Partial Public Class BlogsDataGrid
	   Inherits Page
	  Private blogsContext As New BlogsContext()

	  Public Sub New()
		 InitializeComponent()
		 Me.blogsDataGrid.ItemsSource = blogsContext.Blogs
		 blogsContext.Load(blogsContext.GetBlogsQuery())
	  End Sub

	  Protected Overrides Sub OnNavigatedTo(ByVal e As NavigationEventArgs)
	  End Sub
   End Class
End Namespace

In the constructor, you ask the BlogsContext object to retrieve its Blogs property (an entity list of Blogs) and this collection is assigned as the ItemsSource of the DataGrid. The following line instructs the Blog Context to call its Load member method, passing in the query retrieved by calling GetBlogQuery().  This will be the query that we customized earlier.

The query as you remember, retrieves all of the blogs, ordered by the name of each blog.  This collection is assigned to the DataGrid and the page is displayed when you click on the blogs button.

DataGridRunning

(Click image for full size)

What have you learned, Dorothy?

In this first iteration of moving data from our SQL Server database to the DataGrid on our client, we have examined using the Entity Framework for creating an object orientated model of the data in the database, and using RIA Services both to provide a common set of business classes on the server and the client and to provide transportation of the data from server-side to client-side.

In the next posting on Project Turing,  I will examine both more complex, data retrieval and how we go about modifying the data in the database based on user actions on the client.

Please note that due to Carpal Tunnel Syndrome this posting was dictated and then transcribed by computer.  I apologize for any resulting absurdities.
Novice Previous:  Linq Next: CRUD Operations with Entity Frameworks
Advanced Previous:  Linq Previous:  Linq
Posted in Mini-Tutorial, z Silverlight Archives | Tagged , | 6 Comments

Geek Profiles – Scott Guthrie

Part of what Tim and I do is to provide meaningful connections between the dev team and the community. Today I’m happy to launch a new series of Geek Profiles, highlighting many of the folks who design and implement Silverlight.  These are not intended to be “People Magazine” puff pieces, nor are they  intended to be probing journalistic inquiries into their work; rather a small attempt to bring forward some of the amazing people who work on this project in their own words.

There couldn’t be a better person to begin with than Scott Guthrie.   Scott is Corporate Vice President .NET400px-MIX_Keynote-Scott_Guthrie_09_MS_05_2007 Developer Platform and is responsible for the development of Silverlight, the CLR, ASP.NET, WPF, IIS, and Visual Studio (among others). Not bad for a guy who was born three years after I graduated high school (!)

 He describes himself in a single sentence, “I live in Seattle and develop a few software products for Microsoft.”

Yah.

He has, in fact, become something of an icon among .NET developers, and I’ve commented before that he is the first manager I’ve ever seen at a presentation get a standing ovation before saying a word.

On a personal note, I met Scott twice. The first time was in the very early 1990s at an author’s dinner, where he impressed as a very bright, interested guy, and I remember my editor and I saying “someone to get to know.”  It took about 15 years, until I met him again as part of my interview process at Microsoft (after seeing him give a sea-change presentation on Silverlight, but that is another story).

During the time I was in his organization, I had the opportunity to talk with Scott quite a bit, and he has a unique ability to convince you that there is nothing he’d rather do than spend that 5, 15 or 30 minutes talking to you – everyone feels it.  He is passionate about his work, and about quality and I honestly think he is a bit nonplussed by becoming a geek celebrity.

Here is the brief interview I had with him a couple weeks before PDC:

Q: What are you most enthusiastic about in Silverlight 4?

Scott: I like the power that is now available to out of browser SL applications.  This really opens up a ton of possibilities for developers.

Q:  Do you have any words of advice for Silverlight programmers?

Scott: Use the power of SL for good and not evil :-)  There is a lot of power there and you can do a lot of things – but always make sure that what you do enhances the user experience of your solution as opposed to being purely gratuitous eye-candy. 

Q: Can you tell us something (or some incident) that folks probably don’t know about you?

Scott: I’ve been fortunate to have been at the beginning of several projects – including .NET, ASP.NET SGBobbleHeadand Silverlight.  It has been a fun ride.

Q: You are the only techie I’ve ever seen get a standing ovation before his presentation. What do you think has most contributed to the “Gu” phenomenon?

Scott: It is an odd thing and I’m not really sure what to think about it.  I’m flattered (and kind of embarrassed) by it all. Ultimately it is really the technology people are excited about.  Many, many people enabled the technology – my role in the grand scheme of things is relatively small.  

Scott’s quote on receiving the bobble-head: “Weird. Very weird.”

 

Resources

ScottGu.Com
Scott’s Blog

 

Editor’s note: yes, this was quick and light, and the future profiles will, I hope, have a bit more depth, but the goal is not to create a full profile but rather to introduce some folks on the team you may not know.  I’ll try to include the super-stars like Scott, and Mike Harsh, Karen Corby and Brad Abrams, but also some of the developers who do not present and who you may not yet know.

In any case, I’ll follow up with Scott now that Silverlight 4 is released and try to get a bit more of a look into how he came to do what he does.

 

[Coming up next week: serious mini-tutorials, both on Silverlight From Scratch and on the HyperVideo project, MEF, and much more]

Posted in z Silverlight Archives | Comments Off on Geek Profiles – Scott Guthrie

A Party Game.

Quick Bit

David @Pogue tweeted a link to this NY Times article, reporting that there are [longer] better, faster [stronger] apps available than Shazam (which is about to start charging new midomilogo customers…) so I extensively examined the alternatives for just over  30 seconds,  and bought midomi (get it? Do, Re, Mi:  Mi Do Mi). 

It is faster than  Shazam, and offers more features  but most important you can either type in or, much better, sing or hum the song you are looking for.

After spending about an hour at 3am singing old pop songs in a key entirely my own, I invented the following party game (Sing That Tune) that I give to you in celebration of Silverlight 4 (though it has absolutely nothing to do with Silverlight). If it catches on, remember where you heard it!

  1. Player 1 (Chooser)  tells Player 2 (Singer) the name of a song.
  2. Player 2 sings/hums/etc. into midomi and the results are scored

[Those who require order and the illusion of fairness might decide to rotate the chooser role, and determine the singer role stochastically: perhaps using a die.] 

Scoring:

If midomi finds the song, Singer  scores 3 points if it is the #1 find, 2 points if it is in position #2, otherwise 1 point.

If midomi does not find the song Singer has the option to Challenge. If there is a challenge, the Chooser types in either the name of the song or the artist and has one attempt to find the song in midomi.  If the song is found, Singer loses 3 points, otherwise Chooser loses 5 points

[Could be a fun Silverlight application now that we have microphone support – but the song recognition may be non-trivial)

Posted in z Silverlight Archives | Comments Off on A Party Game.

Silverlight 4 Fluid UI

MiniTutorial

This is the first of many mini-tutorials on Silverlight 4 features.

An enhancement has been made that allows you to add animation when items are added ,or removed from, the list box.  Silverlight 4 adds a new StateGroup to the ListBoxItem class:

ListBoxItemAttributes

A Simple Demo

To demonstrate this, I’ve created a wicked simple demo: the userfluidUIDemo types into the text box, clicks the add button and the text “floats” up into the list.

I begin with a simple Silverlight 4 program in Visual Studio 2010. The grid consists of two rows, whose height is set to the ratio of 5:1.

The top row takes a ListBox and the bottom row a stack panel holding a TextBox and a Button.

The Button’s event handler takes the text from the TextBox and adds it to the ListBox:

   1:  void Add_Click( object sender, RoutedEventArgs e )
   2:  {
   3:     if ( !String.IsNullOrEmpty( StringEntry.Text ) )
   4:     {
   5:        ListOfString.Items.Add( StringEntry.Text );
   6:        StringEntry.Text = string.Empty;
   7:     }  // end if
   8:  }     // end event handler

So Where Is the Magic??

To take advantage of the new FluidUI all you need to do is to set the behavior you want on any or all of the three new Visual States in the LayoutStates group of the ListBoxItem class.

The easiest way to do this is to open the project in Blend and right click on the ListBox. Choose Edit Additional Templates –> Edit Generated Item Container –> Edit a Copy

Name the new template and then click on the ListItem and open the CreateStyleStates tab. For this simple demo, I only modified the Loaded state.

To do so, click on the Loaded state and then expand the timeline. You’ll set new values for the entire Grid (which has 4 sub-elements).

select 0 seconds, and set the opacity to 0 and the  y coordinate of a translate-transform to 200.   Click save keyframe values, and then select 1 second and set the opacity to 1 and the y coordinate to 0. Save the new template.

To connect the new template to the ListBox,, open the Xaml file and add a Style property to the ListBox control (as shown on line 7 below)

   1:  <ListBox x:Name="ListOfString"
   2:     HorizontalAlignment="Stretch"
   3:     VerticalAlignment="Stretch"
   4:     Grid.Row="0"
   5:     Width="225"
   6:     Margin="5"
   7:     ItemContainerStyle="{StaticResource ListBoxItemStyle1}" />

Build and run the program; when you add the text string to the ListBox.Items collection the loaded state is set, your animation is run and the new value floats into place.

Source Code

MainPage.xaml

<UserControl x:Class=”FluidUIDemo.MainPage”

xmlns=”http://schemas.microsoft.com/winfx/2006/xaml/presentation”

xmlns:x=”http://schemas.microsoft.com/winfx/2006/xaml”

xmlns:d=”http://schemas.microsoft.com/expression/blend/2008″

xmlns:mc=”http://schemas.openxmlformats.org/markup-compatibility/2006″

mc:Ignorable=”d”

xmlns:dataInput=”clr-namespace:System.Windows.Control ;assembly=System.Windows.Controls.Data.Input”>

<Grid x:Name=”LayoutRoot”

Width=”250″

Height=”200″>
<Grid.RowDefinitions>

<RowDefinition Height=”5*” />

<RowDefinition Height=”1*” />

</Grid.RowDefinitions>

<ListBox x:Name=”ListOfString”

HorizontalAlignment=”Stretch”

VerticalAlignment=”Stretch”

Grid.Row=”0″

Width=”225″

Margin=”5″

ItemContainerStyle=”{StaticResource ListBoxItemStyle1}” />

<StackPanel Orientation=”Horizontal”

Grid.Row=”1″

Margin=”5″

HorizontalAlignment=”Stretch”

VerticalAlignment=”Stretch”>
<TextBox x:Name=”StringEntry”

Height=”24″

TextWrapping=”Wrap”

Text=””

FontFamily=”Georgia”

FontSize=”14″

Width=”171″

HorizontalAlignment=”Left”

VerticalAlignment=”Bottom”

Margin=”5,0,0,0″ />

<Button Content=”Add”

x:Name=”Add”

Height=”24″

FontFamily=”Georgia”

FontSize=”14″

Width=”51″

HorizontalAlignment=”Left”

VerticalAlignment=”Bottom”

Margin=”5,0,0,0″

IsEnabled=”False” />

</StackPanel>

</Grid>

</UserControl>

MainPage.xaml.cs

using System;
using System.Windows;
using System.Windows.Controls;

namespace FluidUIDemo
{
   public partial class MainPage : UserControl
   {
      public MainPage()
      {
         InitializeComponent();
         Loaded += new RoutedEventHandler( MainPage_Loaded );
      }

      void MainPage_Loaded( object sender, RoutedEventArgs e )
      {
         Add.Click += new RoutedEventHandler(Add_Click);
         StringEntry.SelectionChanged += new RoutedEventHandler( StringEntry_SelectionChanged );
      }

      void StringEntry_SelectionChanged( object sender, RoutedEventArgs e )
      {
         Add.IsEnabled = !String.IsNullOrEmpty( StringEntry.Text );
      }

      void Add_Click( object sender, RoutedEventArgs e )
      {
         if ( !String.IsNullOrEmpty( StringEntry.Text ) )
         {
            ListOfString.Items.Add( StringEntry.Text );
            StringEntry.Text = string.Empty;
         }  // end if
      }     // end event handler
   }        // end class
}           // end namespace

App.xaml Excerpt

<VisualState x:Name="Loaded">
   <Storyboard>
      <DoubleAnimationUsingKeyFrames
         Storyboard.TargetProperty=           "(UIElement.RenderTransform).           (TransformGroup.Children)[3].           (TranslateTransform.Y)"
         Storyboard.TargetName="grid">
         <EasingDoubleKeyFrame KeyTime="0"
                               Value="200" />
         <EasingDoubleKeyFrame KeyTime="0:0:1"
                               Value="0" />
      </DoubleAnimationUsingKeyFrames>
      <DoubleAnimationUsingKeyFrames
         Storyboard.TargetProperty="(UIElement.Opacity)"
         Storyboard.TargetName="grid">
         <EasingDoubleKeyFrame KeyTime="0"
                               Value="0" />
         <EasingDoubleKeyFrame KeyTime="0:0:1"
                               Value="1" />
      </DoubleAnimationUsingKeyFrames>
   </Storyboard>
</VisualState>


Posted in z Silverlight Archives | 4 Comments

The Silverlight HVP Spec

The Silverlight HyperVideo Player: A Community Project

MiniTutorial

The Silverlight HVP Elevator Pitch:

The Silverlight  HyperVideo Player (HVP) will do for Silverlight How Do I Videos what Hypertext did for the Internet: it will provide simple, fast, and easy to use links to additional, supplementary or related information. 

As an example, the user might be watching a video on data binding and the term “Dependency Property” is mentioned and at the same time a link appears. If the user clicks on that link, the video is paused and an explanation of Dependency Properties is provided.

Update 11/20: We have received our MS-PL allowing me to move this project to CodePlex. I will update again with a link once it is in place.   Other updates in-line in red.

 

Summary of Purpose

While I have covered HyperVideo in numerous blog postings and videos in the past, this project will follow the creation and delivery of a complete application.  spinning out mini-tutorials and videos on an extremely wide range of topics.

The project will be designed, developed and delivered in collaboration with many others, both inside of Microsoft and out. 

Scope and Deliverables

This document will serve as the draft  “spec” for the first phases of development. I have intentionally under-documented the spec because of the immutable law that the likelihood of a spec being followed is inversely proportional to its size and (b) the requirements and design will evolve as the community adds ideas and refinement. 

Contributing to the Spec and to the Project

Contributions, refinements and critiques of this document are not only welcome, they are its lifeblood.  For now, I’ll ask that you respond in the comments, , as things evolve I’ll roll out a better mechanism for tracking all of the feedback.

Contributions to the project will be described by the end of the month; for now, if the comments section is insufficient, please feel free to write to me directly.

Core Functionality

The Silverlight HVP will be a modular, extensible, and robust Rich Internet Application that can deliver HyperVideo on any platform that is supported by Silverlight.  Initial requirements include:

  • Present any existing Silverlight How Do I Videos as is.
    • That is, the Silverilght HVP will be backwards compatible with the existing player
    • Any existing video can be enhanced to provide a Table of Contents and/or Hyperlinks either through encoding or marker injection at which point it will be indistinguishable from videos created specifically for the Silverlight HVP
  • TOC TreeDisplay a Table of Contents (TOC) for each video, with affordances for users to move from one topic to the next
    • Current plan is to separate the TOC from the links, presenting the complete Table of Contents when the video begins, but revealing the links as their context arises. 
    • For sufficiently complex Tables of Content we may want to provide the ability to collapse and expand subtopics
  • Display a list of topics as they are mentioned in the video, with each topic’s name acting as a HyperVideo Link.
  • Full support for Closed Captioning and all standard video controls (e.g.,, stop, pause, skip etc.)
  • TOC and Hypervideo Links will be decoupled from the markers in the video so that the links can be modified without changing or re-encoding the video

Potential Features

There are literally dozens of potential additional features, some of which are key to adoption of the player in various settings; others either won’t make it into early versions of the product or will be developed by the community once the open source mechanism is in place.

[Images in this spec are for illustration purposes and are not final visualizations of the application]

Not Just An Application

A primary goal of this project is not only the end product, but the opportunity for discussing Silverlight skills in the context of a real-world application.  Building the Silverlight HyperVideo Player will force consideration of a number of interesting aspects of Silverlight and related technologies.

Some Thoughts on Implementation

There are numerous ways to add markers to video in Silverlight; in the course of developing the Silverlight HVP we will consider two.  The easier approach is to use Expression Encoder to do the initial heavy lifting.  Encoder is designed to record four pieces of information about each marker, the first two of which matter to us.

  1. MarkersThe elapsed time into the video at which the marker appears
  2. A “value” that can have an intrinsic meaning or not as you choose (more about this below)

The other two pieces of meta-data in a marker are the thumbnail and keyframe for each marker; these are typically used to create and manage “chapters” in long videos.

Working With Markers

The Media Element (or a control derived from the Media Element) will fire an event each time a marker is encountered. The HyperVideo player will respond to that event by following the link or opening the associated video as indicated in the metadata that relates a given marker to a given action.

During development of the Silverlight HVP we will explore at least two ways of managing the metadata: storing it in a relational database and storing it in an XML file.

As an off-the-cuff example, the MetaData might be stored in an XML file that looks more or less like this:

<VidepPlayerMetaData>
   <VideoInfo>
     <Title="Data Binding" />
     <URL="http://foo.bar.com" />
   </VideoInfo>
   <Markers>
      <Marker Val="DBX09-001" Action="Play" URL="http://silverlight.net/learn/videos/v1027" />
      <Marker Val="DBX09-002" Action="Play" URL="http://silverlight.net/learn/videos/h1375" />
      <Marker Val="DBX09-003" Action="Link" URL="http://en.wikipedia.org/LCA" />
      <Marker Val="DBX09-004"  />
      <Marker Val="DBX09-005" Action="Play" URL="http://silverlight.net/learn/videos/v1288" />
   </Markers>
</VidepPlayerMetaData>

 

Encoder can create a working player to get us started.

At its heart, the player is a control or a set of controls that can be skinned to change its appearance and can be subclassed to change its behavior. Doing so demonstrates best practices, and significantly simplifies the development effort.

The UI Sketch

Of course, the player created by Encoder is just the starting point it will serve as an essential SilverlightHVPcomponent within a larger application.  The UI design at this point is only a first approximation, subject to significant change, but the rough sketch is enough for me to get started on development.

“You start coding, I’ll go find out what they want.”

The sketch calls for four windows and a menu.

  • The primary player (top center)
  • The Table of Contents (top left)
  • The Links window (top right)
  • The linked-to (target) window (bottom)

Each window will  be resizable, movable, and dockable.

Deliverables and Due Dates:

It is tempting to say that too little is known to create a set of milestones and delivery dates; but projects with no dates have a known finish time: never

Been there, done that, still have the scars. 

Far better to stake yourself to a timetable, then be held accountable; if not to hitting the dates, then to explaining  what has changed that justifies a change.

Thus, after many seconds of careful consideration, here is the timeline for the first iteration of this project.

Task Due
This overview spec completed & published 11/15
Proof of concept deployed  on SilverlightGeek.me 1/1
Delivery of final UI Assets 1/21
First Release Mix10

My plans of course go well beyond Mix, but this is, I hope,  a good start.  I welcome and urge you to join me in an open technical discussion of any and all of this project.

The fine print:

  • Project Turing, and the feedback it engendered, served as a great testing ground for building this kind of application. It was not intended that Turing would be completed, and I’ll suspend it indefinitely.  It is my intent that this project will roll out as an application.
  • I believe this project has tremendous potential, and I’m committed to it, but I’ve been on enough great projects that were stopped before seeing the light of day, that I make these commitments knowing that not everything is under my control (the great delusion is I still think anything is under my control)
Posted in z Silverlight Archives | Tagged , | Comments Off on The Silverlight HVP Spec

On Our Cross Plat Commitment

When I joined Microsoft and started talking about Silverlight, many in the Mac community expressed skepticism about Microsoft’s long-term commitment to the Mac platform. In its most rabid form, the concern was that we were supporting the Mac only preemptively and would drop our support for the Mac as soon as enough Mac developers embraced it (!)

So, 2.5 years later, with the worst not having happened, I have renewed my personal pledge to make sure, to the best of my ability, that Silverlight not only continues to work on the Mac but looks and feels like a Mac app. 

Since I love the Mac, and I love Win7, and I really wanted a Working Laptop2 single machine to walk around with, I recently invested (personally) in a MacBook Pro and put enough RAM in it to happily run both Operating Systems simultaneously.  Here it is at my office with a 24” Cinema display, running both operating systems and pleasing me no end.

I absolutely understand company loyalty (and loving the Mac is not disloyal to Microsoft) but I tend to believe that we do best in recognizing the strengths of our allies and our competition. To quote from a Daft Punk: *

Work it, make it, do it, makes us
Harder, better, faster, stronger

Very much looking forward to PDC – look for me in the The Big Room or check for me on Twitter: @JesseLiberty

 

 

* In the original posting I attributed these words to Kanye West. This was a happy mistake, as your corrections led me to the music of Daft Punk

Posted in z Silverlight Archives | Tagged | Comments Off on On Our Cross Plat Commitment

Commitments

I’ve received a number of messages along the lines of, “Seems like things have really slowed down on your blog” or even “Hey, where’s the signal? Too much noise.”

Fair enough; though this is a common effect of the run up to a major “show” such as PDC (I get caught up in creating material that won’t be released until after the show and things go a bit wobbly here) vacation’s over! Time to Party.

So here are my commitments to you:

In the coming weeks you’ll see:

  1. A series of new and better videos – look for the first ones during PDC.

  2. At least two Silverlight From Zero  mini-tutorials per month, and at least two Intermediate to Advanced mini-tutorials each month. ecqg50Pct

  3. Revitalization of the “Example Code Quality Guarantee” page noting the development environment for all demos.

  4. The HyperVideo Project Spec will be complete by  November 23 (if you wish to contribute to the spec, please send email to jliberty@microsoft.com ) and Coding begins for the  HyperVideo Project Tuesday November 24.

Thanks

jessesig

Posted in z Silverlight Archives | Comments Off on Commitments

Subscribe to 62 Silverlight Twitter’ers.

I’ve created a list that currently follows 62 top-notch Silverlight Twitter participants. twitterBirdSidebarThe list will grow (and be culled) over time, but you can easily sign up to receive tweets from everyone on the list just by clicking on this link and subscribing to the list as a whole. 

 

icon-rss

While you are at it, please take a moment and subscribe to my tweets and to this blog

Posted in z Silverlight Archives | Comments Off on Subscribe to 62 Silverlight Twitter’ers.

Designer v Xaml v Code

MiniTutorialLogo2

This is the second in my new series on Getting Started With Silverlight (please see the first article for information on the series and where to get the software you need).

[updated11/8]

Don’t Start with Xaml…

Until recently, just about every introduction to Silverlight started out by talking about Xaml; the markup language of Silverlight, WPF and Workflow. I believe it is time to stop.

A quick note on Xaml – we all agree how to pronounce it: zam-el to rhyme with camel, but not on how to spell it; most folks use upper case, but  Rob Relyea told me in private correspondence that Xaml was released via MS Open Specification Promise, and prefers it aesthetically, even if he does conform and write XAML like most others programmers. But I’m starting a movement.

(Apologies to Rob and his brother Dave for initially pointing to the latter when I meant the former and confusing MS OSP with ECMA, for which I should be flogged.)

Teaching Xaml first made sense when Xaml was the only (or best) way to create controls. But with a working design surface, Xaml is too high a bar to set just to get started.

Many development environments have gone though a similar evolution: start with HTML, then get a WYSIWYGIYAVL (What You See Is What You Get If You Are Very Lucky) editor.  ASP.NET by hand, then ASP.NET from the toolbox. Etc.

I recommend that if you do not know Xaml you not try to learn it (at first) as you can go very far without doing so, it can be a stumbling block, and the tool will provide incredible help for learning the markup as you need it.

I may be the first person to write down that advice. (I may be stoned to death.) But I suspect I won’t be the last.

Silverlight Without Xaml

To get started, open VS2010 and create a new Silverlight project (I use C# but feel free to use any supported language).  Let’s name it ThreeApproaches

When Visual Studio settles down you’ll probably see a split window with the designer on top and Xaml on the bottom.  Let’s close the Xaml by clicking on the “make top window the only window” button on the far right of the splitter bar

CollapsePane

Open the Toolbox if it is not already open ( Ctrl-W X) and pin it in place.  Then click on the Grid that is the default layout control.  When you click on it, margins will appear and putting the cursor into the top or left margin will offer you a preview of where you might click to create columns or rows respectively. Go ahead and create two rows and two columns, and then shrink the entire grid down to small enough to look ok.

Add Your First Control

Drag a Textblock out of the toolbox and place it more or less in the upper left box and then open the properties window. If the TextBlock’s properties are not displayed, click on the TextBlock to make it the selected control.

Somewhat unusually you set the name of the control at the very top of the NameProperty Properties window

Notice that there are two tabs: Properties and events. Make sure you have Properties selected, and below that you may want to click on the Categorized button rather than the A-Z to make this a bit easier to follow.

Expand the Layout property and by clicking in the black triangle next to both Height and Width (and clicking Reset) you can set the TextBlock’s dimensions to be set in accordance with whatever string (characters) are begin displayed. Set Layoutthe remaining values as shown in the next image, and the TextBlock should  show in the designer as placed in the upper right hand box, 5 pixels from the right and bottom margins.

(To save space I cut out some rows, but you can leave those set to their default values).

Wasn’t that cool? No Xaml needed. But if you want to learn Xaml, aha! there are two great features to help. First, click on the horizontal split button on the far right of the design window. This will restore the split window you started out with.HorizontalSplit

Notice that the Xaml is now shown. Scroll down to line 20 and you should see the definition of the TextBlock, now in Xaml. Notice the 1:1 correspondence with the properties you’ve set.

XamlToProperties
(click on image for full size)

Xaml and Intellisense

Let’s write the second control (TextBox) in Xaml. Click into the Xaml window, XamlIntellisenseand below the TextBlock, type an open angle brace. Intellisense immediately springs forward offering to help you pick the control you want. The more you type, the more Intellisense will narrow in on your choice.

Once you select TextBox, and hit the space bar, again Intellisense jumps in, this time offering suggestions as to the properties you might want to set.

Fill in the property / value pairs as shown below,

   1:      <TextBox Name="Name"
   2:               HorizontalAlignment="Left"
   3:               VerticalAlignment="Bottom"
   4:               Height="25"
   5:               Width="75"
   6:               FontFamily="Georgia"
   7:               FontSize="14"
   8:               Grid.Row="0"
   9:               Grid.Column="1"
  10:               Margin="5" />

Your TextBox will appear in the upper right corner of the designer, with all the properties set to correspond with what you’ve written in the Xaml.

To make the TextBlock (the first control) consistent with this, click on it in theSetTheTextProperty designer, and scroll down to Text Category and drop down the FontFamily to pick “Georgia.”

Set the size to 14 and click the Beer bold button to set it to Bold.

Return to the Text property (above Layout) and change it from TextBlock to Name? and make sure that the margin is set to 5 in the Layout section.

When all of that is done, hit Control-F5 to run the application and you should see a prompt and a textBox into which you can enter your name.RunThe Program

If you like, you can click in the grid but not on one of the two controls and bring up the properties for the Grid. Scroll down to, and expand, the “Other” category and click the checkbox next to “Show Grid Lines” to reveal the rows and columns you created.

Okay, now you know you can write your controls in Xaml, but why bother when you can just drag them onto the designer from the toolbox and set their properties in the Properties window.  I truly believe that the latter approach is faster, less error prone and generally a much better way to get started.

Will you want to hand-code Xaml eventually? Maybe, but my guess is less and less as you get better and better at Visual Studio and, eventually, Expression Blend.

Dynamic Creation of Controls in Code

There is a third way to create controls: dynamically in code.

You can stop reading right here. You won’t need to know this for a long time. I am putting this into this article because (a) this can be a powerful technique when you do need it and (b) for some folks understanding the relationship between dynamically (C#) and declaratively (Xaml) created versions of the same object can be very helpful in groking what Xaml is about.

But your mileage may vary.

It’s All Just Objects

Every object you create in Xaml can also be created at run time in code. To see this, let’s create a second set of prompt and TextBox that will appear when the project is run.

To do so, turn the expander next to MainPage.xaml to reveal the code behind page, MainPage.xaml.cs. (or MainPage.xaml.vb if you are working in VB).

In the constructor, we’ll put a handler for the Loaded event (the loaded event runs when the page is loaded) and we’ll do our work in the event handler Visual Studio creates.

To do this, click into the constructor and type Loaded += then hit Tab twice to let Intellisense create your handler for you.  Click in the handler and delete the exception that Intellisense put there to remind you to implement the handler logic.

We’ll talk about events and event handlers in an upcoming mini-tutorial; but for now, you can ignore the details or feel free to experiment (you can’t break anything).

Creating The TextBlock Dynamically

As noted above, every control can be created as a CLR object, and again Intellisense will help enormously. Begin by instantiating a TextBlock. the Identifier you use (in this case AddressPrompt) will become the Name property.

   1:      void MainPage_Loaded( object sender, RoutedEventArgs e )
   2:      {
   3:        TextBlock AddressPrompt = new TextBlock();
   4:      }

You will now add each property to the instance of TextBlock, though here you must be sure to be type-safe. Let’s walk through it.

First, you’ll want to set the HorizontalAlignment, which turns out to be an HorizAlignmentenumerated constant. Again, Intellisense will help by offering the legitimate values

Fill in the Vertical Alignment in the same way.

When you try to fill in the Margin as a value, you’ll not the red squiggly line indicating something isMargin wrong. Hover over the Margin property and the tag will indicate the type of the Margin: Thickness. At this point you can open the help files to read about the Thickness type, or you can just instantiate one and see how that goes. I personally prefer the latter. Not onlyThickness Help does Intellisense show you that there are three possible constructors (which you can scroll through with the arrow keys) but it identifies the purpose of each parameter and guides you through filling them in. While I show the third constructor here, which lets you set the left, top, right and bottom margin, we’ll actually use the second constructor which lets you assign one value for all four.

Next we want to set the Height and Width. Hovering over each will reveal that they are doubles, but in this case we want to set them to “auto” – a quick check of the documentation reveals that this is accomplished by assigning the static value  Double.NAN – a flag for the compiler to set them automatically.

You can set the FontFamily and FontSize as a string and a double FontWeightsrespectively, but set the FontWeight using the enumeration.

Here is the code we have so far

   1:  TextBlock AddressPrompt = new TextBlock();
   2:        AddressPrompt.HorizontalAlignment =
   3:            System.Windows.HorizontalAlignment.Left;
   4:        AddressPrompt.VerticalAlignment =
   5:            System.Windows.VerticalAlignment.Bottom;
   6:        AddressPrompt.Margin = new Thickness( 5d );
   7:        AddressPrompt.Height = double.NaN;
   8:        AddressPrompt.Width = double.NaN;
   9:        AddressPrompt.FontFamily =
  10:            new FontFamily( "Georgia" );
  11:        AddressPrompt.FontSize = 14d;
  12:        AddressPrompt.FontWeight = FontWeights.Bold;

Placing the Control into the Grid

We placed the first controls into the Grid by writing

Grid.Row = "0"
Grid.Column = "1"

But of course, neither TextBlock nor TextBox has a Grid.Row property.  These GridSetColumnare Extended Properties, properties defined in Grid but borrowed by other elements to assist in their placement. The C# equivalent is to call the ??? methods of the Grid class, passing the UIElement (in this case, AddressPrompt) that you want to place in the grid, and then the column number and  row respectively.

Grid.SetColumn( AddressPrompt, 0 );
Grid.SetRow( AddressPrompt, 1 );

That done, the last step is to add the new element to the Grid itself, by referencing the Children collection of the particular Grid instance, and calling the Add method on that collection, passing in our Element:

LayoutRoot.Children.Add( AddressPrompt );

We can then follow a very similar process for the Address text box. The one interesting addition I’ll make is to set the color on the text in the TextBox. You do this by setting the Foreground property, and you must assign it a SolidColorBrush as its value. You can instantiate a SolidColorBrush by passing in a Color from the Colors enumeration,

AddressInput.Foreground = new SolidColorBrush( Colors.Blue );

When you look at the designer, you will not see either of these controls; they RunningProgramwon’t exist until the program runs. Press Control-F5 and try out your new program, however, and you’ll see that the dynamically instantiated controls are indistinguishable from the declarative (Xaml) controls; at least to all appearances:

You Can, But Don’t.

Even though dynamic declaration of elements takes many more lines of code; C# developers are often tempted to eschew Xaml and go with C# – after all; it is a tool they know.

Xaml has many advantages, however, not least of which is that it is highly toolable.  That means that it works extremely well with the Visual Studio Designer and with Expression Blend, which in the long run means far faster development, better looking and easier to maintain applications, and a much easier interaction with designers.

The Source Code

For completeness, here is the Xaml file followed by the C# file:

MainPage.Xaml

<UserControl x:Class="ThreeApproaches.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    d:DesignHeight="300" d:DesignWidth="400">
    <Grid x:Name="LayoutRoot" Background="White"
        Height="135"
        Width="250">
    <Grid.RowDefinitions>
      <RowDefinition Height="1*" />
      <RowDefinition Height="1*" />
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
      <ColumnDefinition Width="1*" />
      <ColumnDefinition Width="2*" />
    </Grid.ColumnDefinitions>
    <TextBlock Grid.ColumnSpan="1"
               HorizontalAlignment="Right"
               Margin="5"
               Name="myFirstTextBlock"
               Text="Name?"
               VerticalAlignment="Bottom" />
    <TextBox Name="Name"
             HorizontalAlignment="Left"
             VerticalAlignment="Bottom"
             Height="25"
             Width="75"
             FontFamily="Georgia"
             FontSize="14"
             Grid.Row="0"
             Grid.Column="1"
             Margin="5" />
  </Grid>
</UserControl>

[Note that I cleaned up the Grid columns and rows, using relative sizing (1*) and making the relative sizes of the columns 1:2 – all of this to be explained in an upcoming Mini-tutorial]

MainPage.Xaml.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
namespace ThreeApproaches
{
  public partial class MainPage : UserControl
  {
    public MainPage()
    {
      InitializeComponent();
      Loaded += new RoutedEventHandler( MainPage_Loaded );
    }
    void MainPage_Loaded( object sender, RoutedEventArgs e )
    {
      TextBlock AddressPrompt = new TextBlock();
      AddressPrompt.HorizontalAlignment =
        System.Windows.HorizontalAlignment.Left;
      AddressPrompt.VerticalAlignment =
        System.Windows.VerticalAlignment.Bottom;
      AddressPrompt.Margin = new Thickness( 5d );
      AddressPrompt.Height = double.NaN;
      AddressPrompt.Width = double.NaN;
      AddressPrompt.FontFamily =
        new FontFamily( "Georgia" );
      AddressPrompt.FontSize = 14d;
      AddressPrompt.FontWeight =
        FontWeights.Bold;
      AddressPrompt.Text = "Address ?";
      Grid.SetRow( AddressPrompt, 1 );
      Grid.SetColumn( AddressPrompt, 0 );
      LayoutRoot.Children.Add( AddressPrompt );
      TextBox AddressInput = new TextBox();
      AddressInput.HorizontalAlignment =
        System.Windows.HorizontalAlignment.Left;
      AddressInput.VerticalAlignment =
        System.Windows.VerticalAlignment.Bottom;
      AddressInput.Margin = new Thickness( 5d );
      AddressInput.FontFamily =
        new FontFamily( "Georgia" );
      AddressInput.FontSize = 14d;
      AddressInput.Foreground =
        new SolidColorBrush( Colors.Blue );
      AddressInput.Width = 100d;
      AddressInput.Height = 25d;
      Grid.SetColumn( AddressInput, 1 );
      Grid.SetRow( AddressInput, 1 );
      LayoutRoot.Children.Add( AddressInput );
    }
  }
}

Next in this series: Creating Input Forms with the Silverlight Toolkit

(Note, when the article is posted, the name of the next posting will become a link)

Posted in Mini-Tutorial, z Silverlight Archives | Tagged | 1 Comment

Silverlight From Zero

MiniTutorialLogo2

This is the first of a series of blog posts directed at folks who are new to Silverlight and/or want to brush up on the fundamentals.  It will consist of mini-tutorials on topics I think need more coverage, and links to existing mini-tutorials, tutorials and videos. We begin… at the beginning.

What is Silverlight, Why Do I care?

This is the traditional place to start, but in all probability if you are here, you know the answer. In brief: Silverlight is Microsoft’s Rich Internet Application enabling technology. The goal is to create applications that are delivered by the browser but which offer the user experience of a desktop application.  There is no question that using a RIA technology offers the ability to create a quality of experience that cannot be matched by more traditional approaches.

Where Do I Get It?

Everything you need to start writing Silverlight applications is available on our Get Started page.WebPlatform

If you don’t already have Visual Studio, consider starting with Visual Web Developer (VWD). You can download both VWD and Silverlight together using the Web Platform Installer

Otherwise,  you may want to take a look at the more powerful  Visual Studio 2008 or the new beta of Visual Studio 2010.  Once you get serious with Silverlight you’ll really want  Expression Blend.  

Navigating the Get Started Page

On Get Started you’ll find an array of options. The first option tells you how to get Visual Studio or VWD, and options 2, 3 and 5 while incredibly useful, are not required for your initial foray into Silverlight… so just grab option 4.

Quick Tour?StartLearningAbridged

In the next section on the Get Started page, you’ll find a quick tour of Silverlight.  

This is a great way to get going. On the other hand, if you are going to follow this series, you may want to watch just #1 (Getting Started video) and hold off on the rest as I’m  going to integrate all of that material (including Tim’s terrific 8 part blog series) as we go.

The Tools

Tim’s excellent first video in his series will definitely get you started on the right foot using the tools.  TimH

I’ve never fully understood why developers don’t spend more time learning the details of Visual Studio; it is, after all, our fundamental tool, the environment in which we live all day. Time spent on getting all you can out of Visual Studio will pay dividends for a long time.

Diving In

With that, you are ready to dive into Silverlight. Arguably, the best way to get a handle on what Silverlight is, is to write a program that uses it to accomplish something reasonably useful. A good starter video on building an application (a bit old, but still correct) is this gentle intro to creating a Silverlight application with Visual Studio, using the Canvas to lay out controls.  Then read Part 2 in Tim’s series on layout.

Next in this series: Three Approaches: Designer, Xaml or Dynamic

 

Posted in z Silverlight Archives | Tagged | Comments Off on Silverlight From Zero

Silverlight Synchronicity

SilverlightConsulting

At Mix ‘07 I watched Scott Guthrie’s keynote introduction of Silverlight,  and it was a watershed moment in my career.  Within 48 hours I had pivoted my consulting business to focus entirely on this new and game-changing  technology; a few months later I ended 15 years as an independent to join Microsoft as Silverlight Geek, a job that has been immensely rewarding.

On a personal (and seemingly unrelated) note; while my older daughter was in high school she became fluent in American Sign Language (ASL) under the tutelage of two terrific teachers, one hearing, one deaf. She joined the school’s justifiably famous Pocket Players bi-lingual (ASL and spoken English) theater group under the  direction of the incomparable and greatly RobinWoodmissed Robin Wood, and the extraordinary  natural-born-teacher Ron Galiazzo, (who has been patient  enough to teach me a little faltering ASL as well). My daughter learned, and taught us, great respect for Deaf culture,  and I had the incredible pleasure of watching her perform and then taking part with her in a celebration of Chinese American Deaf culture in Boston, where I spent the evening talking happily in broken-ASL with my tablemates.

The third piece of yesterday’s synchronicity touches on the person who most famously embodied the stereotype-shattering new awareness of all that the hearing world has historically gotten wrong about Deaf culture, and the abilities and supposed limitations of deaf people, Marlee Matlin. Her singular and award winning performances in Children of  A Lesser God and The West Wing have had an impact on me and so many others,  for over twenty years.

All of this came together spectacularly yesterday when I posted a small blog entry on the ability of Silverlight to support closed captioning and my commitment to including Accessibility in the design of the HyperVideo project.MatlinTweet This was picked up, I’m incredibly happy to say, by Ms. Matlin who tweeted about it to the National Association of the Deaf  (NAD) and “everyone.”  I have to say, that not only made my day (week, month!) but brought home how much impact Silverlight can have. 

I don’t want in any way to exploit Ms. Matlin’s tweet; this is not about promoting our technology as much as enjoying having made indirect contact with someone whose work I admire, and sharing that joy with the Silverlight community. It was very cool to see what she wrote, but it is also a reminder how vital it is, to get these things “right,” including remembering that adding Accessibility isn’t a trivial decision; but one that affects the ability of a great many people to use the products that Silverlight enables. 

Posted in z Silverlight Archives | Comments Off on Silverlight Synchronicity

Hypervideo, Closed Captions & Accessibility

 

 

The Closed Captioning For Silverlight Media page at T2Sami.com says in its commentary: 

A number of very sophisticated Silverlight Video players are under development: some open source, some proprietary…. The commitment to captioning in Silverlight is not so well supported. If it is included at all, it is frequently an afterthought.

In my initial series on HyperVideo I started with the media player emitted by Encoder, and stripped out the Closed Captioning button. That was unnecessary and I regret it. Please take this posting as my pledge not to have closed captioning and other accessibility issues be an afterthought; but rather they will be an integral part of the spec I will deliver for HyperVideo on December 1 for the renewed HyperVideo project.

In the  interim, please take a look at this excellent tutorial on Captioning In Silverlight on the Accessible Media Project and also be sure to check out these two open source projects:

Posted in z Silverlight Archives | Tagged | Comments Off on Hypervideo, Closed Captions & Accessibility