On Learning New Technology – Controls Toolkit & Examples

 ScottPDC I had a great PDC.  I arrived with a schedule filled with sessions I intended to go to, and (shhhhh!) I skipped them all (except, ScottGu’s keynote and Scott Hanselman’s BabySmash both of which were (predictably) great). 

The reason I skipped all the others (and there were a lot of excellent talks that I will now have to settle for seeing the recordings)  is that I had the singular opportunity to not only talk with, but truly engage with some amazing developers. 

Microsoft puts on 3 major shows a year, and PDC is the most “forward looking” of the three, which means, ultimately, that a lot of what you see at PDC you probably can’t put into production code today.  Given that and the “all in” cost of attending (admission, transportation, accommodations and missed work) it tends to attract some very serious geeks. And that can make for some very interesting conversations on any number of topics.

Terse, Complex or Dead Simple?

One topic that came up a lot was the universal sense of being overwhelmed by the sheer volume of new technology, and how each developer coped with learning all the new material. This lead to some fascinating discussions about how technology is taught, documented, and explained. It was very clear that there would never be consensus on the "best" method; there can be no one best way to teach because there  is no single learning style. That said, there did seem to be two schools of thought about examples. One group seemed to strongly favor real-world examples even at the cost of a little complexity;  the other to strongly favor incredibly simple examples even at the cost of being overtly artificial.

It is clear that I favor dead-simple examples, and I can trace that directly to learning to program what turned out to be a terrific ISAM package in C in the mid 1980s. The problem, though was in their documentation. Each of their examples was incredibly cool, but amazingly opaque. It was only after I stripped away all the indirection and programming elegance that I realized that there were just half a dozen relatively straight-forward function calls to manage. I ended up creating my own set of examples that were 1/10 the size of theirs and 10 times easier to grok. It was a lesson that is seared into my writing center.

Revisiting the Controls Toolkit Examples

The incredible folks in Shawn Burke’s group have released the Silverlight Control Toolkit and it comes with what I consider to be really terrific documentation, plus source code plus examples and so Bob’s Your Uncle and you’re done.  But while I really like what they’ve done, I’m going to take a shot at revisiting some of the samples to really tear it down to the simplest and most visible moving parts, and along the way I’ll also take a look at using the controls in both Blend and Visual Studio.  This will be an on-going effort, over a few weeks and depending on your comments and what else comes up, we’ll take some detours and delve into some of the nuances of how these controls can be used in unexpected ways.

Please click here to download the Controls Toolkit

I set out today to begin work on the AutoComplete control, which has all sorts of interesting nooks and crannies, but I quickly discovered that I wanted to create my own data to explore this control (and others), and this is where ADD is either a curse or a blessing, because I spent quite a bit of time spelunking through the open file dialog, and the scroll viewer (not to mention deciding on the right kind of generic collection.  So, since it is the weekend, let’s actually start there and we’ll get to the AutoComplete control (part 1 of many) in the next entry.

Creating A Data Set of Words

What I wanted was a very large set of words (so that when we’re working with the auto-complete you can start typing (e.g., ) acc and get quite a few words that match (accent, accompany, accordand, accordingly, accosted, account, accounted, accumulate, accurate, accustomed)  That lets you continue to narrow, adding an o knocks out accent and accumulate, accurate and accustomed. adding an r gets you down to just two words: accordand and accordingly.  You see the point.

On the other hand, I did not want you to have to download a large file just to make this work, and besides, it is more interesting if you can put in your own set.  So! it doesn’t take much to write a program that reads a file from your disk (Silverlight doesn’t mind reading from your disk, it is writing to your disk where it is very careful).  We take the file and read in all the words and after a bit of hocus pocus create a collection of unique words (that is, we eliminate all the duplicates and all the punctuation).  Sort the collection and we have just what we need.

Here is how I chose to do it.

First, i needed a file, so I went to Project Gutenberg (a wonderful project well worth your time) where I was able to download a text version of Swan’s way by Marcel Proust (public domain).  That will serve nicely as a source of words (and some interesting words at that!)

Second, I created a very simple UI as this is really just a utility. The UI has a button to open the file dialog, a TextBlock to let me know what is happening, and then two large TextBlocks encased inside ScrollViewers to show me the words I’ve retrieved. The left ScrollViewer displays the words in the order they were retrieved, the right displays them in alphabetical order,

AutoFill
(Figure cropped)

Notice that I’ve only captured 4,298 unique words. That is because I told the code to stop retrieving words once it hit 100,000 characters – why sit around all day on a weekend and 4K words is plenty.

Here’s the code walkthrough; nothing terribly complicated, though with luck you’ll find something new or useful…

<UserControl x:Class="AutoFill1.Page"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Width="400" Height="600">
    <Grid x:Name="LayoutRoot" Background="White">
        <Grid.RowDefinitions>
            <RowDefinition Height="1*" />
            <RowDefinition Height="5*" />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="1*" />
            <ColumnDefinition Width="1*" />
        </Grid.ColumnDefinitions>
        <Button x:Name="OpenFile" Content="Open File"
                 Height="30" Width="60" Margin="10"
                 HorizontalAlignment="Left" VerticalAlignment="Top"  />
        <TextBlock x:Name="Totals" Width="200" Height="30" 
            Text="Waiting..."  Grid.Column="1" VerticalAlignment="Top" 
            Margin="0,20,0,0"/>

        <ScrollViewer x:Name="WordDisplayViewer"  BorderBrush="Black" 
          BorderThickness="1"  Grid.Row="1" Grid.Column="0" Margin="5" 
          Background="Bisque" VerticalScrollBarVisibility="Auto" 
          HorizontalScrollBarVisibility="Hidden" VerticalAlignment="Stretch" 
          Width="190" >
            <TextBlock x:Name="WordDisplay" TextWrapping="Wrap" Text="Words" Width="160" />
        </ScrollViewer>
        <ScrollViewer BorderBrush="Black" BorderThickness="1" Grid.Row="1" 
            Grid.Column="1" Margin="5" Width="190" Background="Wheat" 
            VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Hidden"
            VerticalAlignment="Stretch" HorizontalAlignment="Stretch">
             <TextBlock x:Name="SortDisplay" TextWrapping="Wrap" Width="160"  
               Text="SortDisplay" />
        </ScrollViewer>
    </Grid>
</UserControl>

The key to having a nice scrolling block of text is to have the width of the text box be less than the width of the scrollViewer – enough to allow for the scroll bars.

In Page.xaml.cs I declare two private members, a StringBuilder and a List<String> and in Page_Loaded I provide the button’s event handler, which opens the file dialog,

public partial class Page : UserControl
{
   private StringBuilder sb = new StringBuilder();
   private List<string> words = new List<string>();

   public Page()
   {
      InitializeComponent();
      Loaded += new RoutedEventHandler( Page_Loaded );
   }

   void Page_Loaded( object sender, RoutedEventArgs e )
   {
      OpenFile.Click += new RoutedEventHandler( OpenFile_Click );
   }

The job of the event handler is to present the file dialog and then if hte user picks a file to open that file as a file stream, read through each line and using the string builder create a nice long string of up to 100,000 characters. 

void OpenFile_Click( object sender, RoutedEventArgs e )
{
   OpenFileDialog openFileDialog1 = new OpenFileDialog();

   // Set filter options and filter index.
   openFileDialog1.Filter = "Text Files (.txt)|*.txt|All Files (*.*)|*.*";
   openFileDialog1.FilterIndex = 1;

   openFileDialog1.Multiselect = false;

   // Call the ShowDialog method to show the dialog box.
   bool? userClickedOK = openFileDialog1.ShowDialog();

   // Process input if the user clicked OK.
   if ( userClickedOK == true )
   {
      // Open the selected file to read.
      System.IO.Stream fileStream = openFileDialog1.File.OpenRead();

      using ( System.IO.StreamReader reader = new System.IO.StreamReader( fileStream ) )
      {
         string temp = string.Empty;
         try
         {
            do
            {
               temp = reader.ReadLine();
               sb.Append( temp );
            } while ( temp != null && sb.Length < 100000 ) ;
         }
         catch
         {
         }
      }
      fileStream.Close();

(Notice that this is not exactly industrial-strength code. )

SwanBook 

In any case, once I have my string I break it into words by using the regular expression "\b" which separates the string into words which I put in an array of strings called AllWords.

If you are interested in regular expressions but you find books and articles on them too abstract, I can’t recommend RegEx Buddy highly enough.  You put in some text, and it (a) helps you build up your regular expression and (b) lets you test and (c) explains what works, what doesn’t and why.  Caveat: it is not free.

 

RegExBuddy

(Regex Buddy at work – from their site)

 

In any case, once my string is broken into words, I then iterate through each word to see if I have it already (I want only one copy of each word) and if not, I check to see if it is "junk" (has punctuation, numerals, etc.).  If it passes muster, I add it to my list<string> and once done I display the results,

fileStream.Close();
string pattern = "\\b";
string[] allWords = 
System.Text.RegularExpressions.Regex.Split( 
                  sb.ToString(), pattern );
foreach ( string word in allWords )
{
   if ( words.Contains( word ) == false )
   {
      if ( word.Length > 0 &&  ! IsJunk( word ) )
      {
         words.Add( word );
      }     // end if not junk
   }        // end if unique
}           // end for each word in all words
Totals.Text = words.Count + " unique words added.";
Display();
}           // end if user clicked OK in dialog
             // end method

To be able to display and use the words, I’ve created two properties,

public List<string> Words
{
   get { return this.words; }
}
 
public List<string> SortedWords
{
   get 
   { 
      List<string> temp = this.words;
      temp.Sort();
      return temp;
   }
}

Here are the two missing helper methods:

private void Display()
{
   WordDisplay.Text = string.Empty;
   SortDisplay.Text = string.Empty;
   foreach ( string s in Words )
   {
      WordDisplay.Text += " " + s;
   }
   foreach ( string s2 in SortedWords )
   {
      SortDisplay.Text += " " + s2;
   }
}
 
private bool IsJunk( string theWord )
{
   foreach ( char c in theWord.ToCharArray() )
   {
      if ( char.IsPunctuation( c ) || char.IsDigit( c ) || char.IsSymbol( c ) || char.IsSeparator( c ) )
         return true;
   }
   return false;
}

The very next thing to do (now that this works) is to refactor into three classes: the original page, the code that opens the dialog box and the code that creates the data structure of words.  I’ll do that next time and use that data structure to illustrate how to use the autocomplete box.

Posted in z Silverlight Archives | Comments Off on On Learning New Technology – Controls Toolkit & Examples

Themes Revisited: The Implicit Style Manager [Updated!]

In a recent post on theming using the new Themes from the Controls Toolkit I showed that you can add a theme to your Xaml and then add a container as the content of that theme.

A powerful alternative is to use the ImplicitStyleManager to apply the theme to a single control or, more commonly, to a container (for example, a grid) and all its controls.

To do so, you’ll want to provide the Silverlight URI to the .xaml file that defines the theme, which you can copy straight from the source code provided with the Toolkit into your project.

ThemeXamlInProject

Based on a question I received, I realized I should have provided more clarification:

The exact steps for adding this Xaml file are to go to the source files for the toolkit, navigate to the Themes pseudo-folder and grab Themes.xaml from under Controls.Theming.ShinyBlue and copy it to your project,  renaming it to Microsoft.Windows.Controls.Theming.ShinyBlue.xaml  (as shown).

This name is based on the fact that the file you are grabbing is from the Controls.Theming.ShinyBlue project and Controls is identified in the file as follows:

xmlns:controls=”clr-namespace:Microsoft.Windows.Controls; assembly=Microsoft.Windows.Controls”

With that you are ready to create your page, which you can certainly lay out in either Blend or Visual Studio,

CreatingThemeTestInBlend

On clicking the Apply Theme in the upper left hand corner we’ll apply the theme that is supplied as part of the control toolkit. We’ve already added the .xaml file that defines the ShinyBlue theme, so we need only add a reference to the Theme support dlls,

ThemeSupportDLLs

and the using statement at the top of Page.xaml.cs so that we can refer to the ImplicitStyleManager,

using Microsoft.Windows.Controls.Theming;

That done, we create the event handler to respond to the press of the Apply Theme button,

void applyTheme_Click( object sender, RoutedEventArgs e )
{

Within this method we’ll create a Silverlight URI that points to the Xaml file. The URI constructor takes the Silverlight path to the ShinyBlue.xaml and the enumerated constant UriKind.Relative. With that, we are ready to call three static methods on ImplicitStateManager:

1. SetResourceDictionaryURI takes the control that we want to set the theme for (in our case the Layout Root, which will also apply the theme to all its contained controls) and the URI.

2. SetApplyMode again takes the control we’re setting the theme for, but this time the second parameter is one of the ImplicitStyleApplyMode constants ( the possible values are Auto, OneTime or None).

3. Apply which applies the style and takes the single parameter of the control we’re applying the style to.  Here is the complete Page.xaml.cs, with the code we’ve just discussed at the end.

using System;
using System.Windows;
using System.Windows.Controls;
using Microsoft.Windows.Controls.Theming;

namespace ThemesWithISM
{
   public partial class Page : UserControl
   {
      public Page()
      {
         InitializeComponent();
         Loaded += new RoutedEventHandler( Page_Loaded );
      }

      void Page_Loaded( object sender, RoutedEventArgs e )
      {
         applyTheme.Click += new RoutedEventHandler( applyTheme_Click );
      }

      void applyTheme_Click( object sender, RoutedEventArgs e )
      {
         Uri uri = new Uri( @"ThemesWithISM;component/Microsoft.Windows.Controls.Theming.ShinyBlue.xaml", UriKind.Relative );
         ImplicitStyleManager.SetResourceDictionaryUri( LayoutRoot, uri );
         ImplicitStyleManager.SetApplyMode( LayoutRoot, ImplicitStylesApplyMode.Auto );
         ImplicitStyleManager.Apply( LayoutRoot );
      }
   }
}

 

 

 

Applying The Style

When the page is first displayed no style is attached,

BeforeApplyingTheme

Clicking on the Apply Theme button invokes the event handler which calls the ImplicitStyleManager methods and applies the theme,

AfterApplyingTheme

Posted in z Silverlight Archives | 1 Comment

Toolkit release & Themes

 

Today at Microsoft PDC, Scott Guthrie demonstrated some of the new controls that have been provided as a part of the Silverlight Toolkit. 

The Silverlight Toolkit was previously named the Silverlight Control Pack

This toolkit provides a set of controls and themes for Silverlight 2. 

  • AutoCompleteBox
  • Chart
  • DockPanel
  • Label
  • Expander
  • TreeView
  • UpDown
  • ViewBox
  • WrapPanel
  • ImplicitStyleManager

These controls and their source code are available with Ms-Pl licensing on Codeplex. 

Historically, charting has been an extra-cost item, provided by third party vendors, but the Silverlight team is providing an extensive and extensible set of chart controls, with source code for free. We will be creating numerous HDI videos and tutorials to assist with getting the most from these controls and Tim has already posted a mini-tutorial to get you started.

I’ll kick of an examination of themes with a very simple application. To get started add the theme dll references to your application

ThemesDLLs

Note that for convenience, I’ve chosen to put my Controls dlls into a subdirectory of C:\Program Files (x86)\Microsoft SDKs\Silverlight\v2.0 though this is not required.

You can now add a theme either in Blend or in Visual Studio. Let’s start in Blend, but also look in Visual Studio to see how the Xaml is placed and, at least at the most superficial level, what the Theme does for you.

Themes in Blend

Once the themes are in your references, you can treat them as controls by extending the chevron, clicking on “show all” and choosing “custom controls” (remember, these controls are not in the core).

AssetLibraryThemes

You can add a theme to your page just as you add any control. typically, you will want to add a theme to a high level FrameworkElement, as all of the children (contained controls) will be themed.

Once you add the theme, you’ll want to double click on it, making it the container, so that additional controls will be “within” the theme, and thus the theme will be applied to those controls.

Within that theme can be one control, but of course that control can be (and should typically be) a container control, and so we end up with something like this,

   1: <UserControl
   2:     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   3:     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   4:     x:Class="ThemesTest.Page"
   5:     Width="800" Height="600" 
   6:     xmlns:shinyRed="clr-namespace:Microsoft.Windows.Controls.Theming;assembly=Microsoft.Windows.Controls.Theming.ShinyRed" 
   7:     xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
   8:     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
   9:     mc:Ignorable="d">
  10:  
  11:     <Grid x:Name="LayoutRoot" Background="White">
  12:         <shinyRed:ShinyRedTheme HorizontalAlignment="Stretch" Margin="0" Width="Auto" 
  13:          FontFamily="Verdana" FontSize="24" FontWeight="Bold">
  14:             <Grid Height="Auto" x:Name="InnerGrid" Width="Auto">
  15:               <Grid.ColumnDefinitions>
  16:                     <ColumnDefinition Width="0.1*"/>
  17:                     <ColumnDefinition Width="0.1*"/>
  18:                 </Grid.ColumnDefinitions>
  19:  
  20:                 <Button x:Name="btn"
  21:                     Height="72" 
  22:                     HorizontalAlignment="Left" 
  23:                     VerticalAlignment="Bottom" 
  24:                     Width="244" Margin="0" 
  25:                     Content="This button is themed" 
  26:                     FontSize="18"  FontFamily="Verdana"/>
  27:                 <CheckBox 
  28:                     HorizontalAlignment="Left" 
  29:                     VerticalAlignment="Bottom" 
  30:                     Margin="10,0,0,0" 
  31:                     Width="150" Height="50"
  32:                     Content="CheckBox"
  33:                     Grid.Column="1" />
  34:             </Grid>
  35:         </shinyRed:ShinyRedTheme>
  36:     </Grid>    
  37: </UserControl>

Notice that we start with on outer grid, within that grid is a theme and inside that theme is another grid. We’re now back to programming exactly the way we always have; doing nothing special to the controls; but they are created within a theme, and thus the the theme is applied to the button and checkbox,

TwoThemedControls

To get a sense of how this affects a variety of controls, I created a slightly larger application that has two grids, one with a number of controls that are themed, the second with the same controls unthemed.

Here’s the page.xaml,

<UserControl xmlns:basics="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls" 
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="themes1.Page"
Width="700" Height="650" 
xmlns:rainerPurple="clr-namespace:Microsoft.Windows.Controls.Theming;assembly=Microsoft.Windows.Controls.Theming.RainierPurple" 
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d">
<Grid x:Name="outer">
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="1*" />
        <ColumnDefinition Width="1*" />
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
        <RowDefinition Height="1*" />
        <RowDefinition Height="1*" />
    </Grid.RowDefinitions>
    <rainerPurple:RainierPurpleTheme Margin="0,0,0,0"     >
        <Grid x:Name="LayoutRoot" Background="White" Height="600" Width="320" Grid.Column="0" Grid.Row="0">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="0.1*"/>
                <ColumnDefinition Width="0.1*"/>
            </Grid.ColumnDefinitions>
            <Grid.RowDefinitions>
                <RowDefinition Height="0.1*"/>
                <RowDefinition Height="0.1*"/>
                <RowDefinition Height="0.8*"/>
            </Grid.RowDefinitions>
            <Button Width="100" Content="Click Me" x:Name="myButton" HorizontalAlignment="Left" FontFamily="Verdana" FontSize="14"  Margin="5,0,0,0" VerticalAlignment="Bottom"/>
            <CheckBox Grid.Column="1" Content="Theme engaged" HorizontalAlignment="Left" IsChecked="True" FontSize="14" FontFamily="Verdana" Margin="5,0,0,0" d:LayoutOverrides="Height" VerticalAlignment="Bottom"/>
            <basics:Calendar DisplayMode="Month" IsTodayHighlighted="True" Grid.Row="2" Grid.Column="0" HorizontalAlignment="Left" Margin="5,0,0,0" Width="150" VerticalAlignment="Top" />
            <PasswordBox Width="111" Grid.Row="1" Grid.Column="0" HorizontalAlignment="Left" Height="30" Margin="5,0,0,0" VerticalAlignment="Bottom" RenderTransformOrigin="0.5,0.5" />
            <StackPanel HorizontalAlignment="Stretch" Margin="0,0,0,0"
            Grid.Row="1" Grid.Column="1" Orientation="Horizontal">
                <RadioButton x:Name="rb1" GroupName="Grp1" Content="yes" IsChecked="true" Width="50" Height="20" HorizontalAlignment="Left" VerticalAlignment="Bottom" Margin="5,0,0,0" />
                <RadioButton x:Name="rb2" GroupName="Grp1" Content="no" Width="50" Height="20" HorizontalAlignment="Left" VerticalAlignment="Bottom" Margin="5,0,0,0" />
            </StackPanel>
            <Button Height="42" Margin="36,82,46,0" VerticalAlignment="Top" Grid.Column="1" Grid.Row="2" Content="Button"/>
        </Grid>
    </rainerPurple:RainierPurpleTheme>
    <Grid x:Name="LayoutRoot2" Background="White" Height="600" Width="320" Grid.Row="0" Grid.Column="1" >
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="0.1*"/>
            <ColumnDefinition Width="0.1*"/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="0.1*"/>
            <RowDefinition Height="0.1*"/>
            <RowDefinition Height="0.8*"/>
        </Grid.RowDefinitions>
        <Button Width="100" Content="Click Me" x:Name="myButton2" HorizontalAlignment="Left" FontFamily="Verdana" FontSize="14" Margin="5,0,0,0" VerticalAlignment="Bottom"/>
        <CheckBox Grid.Column="1" Content="Theme engaged" HorizontalAlignment="Left" IsChecked="True" FontSize="14" FontFamily="Verdana" Margin="5,0,0,0" d:LayoutOverrides="Height" VerticalAlignment="Bottom"/>
        <basics:Calendar DisplayMode="Month" IsTodayHighlighted="True" Grid.Row="2" Grid.Column="0" HorizontalAlignment="Left" Margin="5,0,0,0" Width="150" VerticalAlignment="Top" />
        <PasswordBox Width="111" Grid.Row="1" Grid.Column="0" HorizontalAlignment="Left" Height="30" Margin="5,0,0,0" VerticalAlignment="Bottom" RenderTransformOrigin="0.5,0.5" />
        <StackPanel HorizontalAlignment="Stretch" Margin="0,0,0,0"
            Grid.Row="1" Grid.Column="1" Orientation="Horizontal">
            <RadioButton x:Name="rb1a" GroupName="Grp1" Content="yes" IsChecked="true" Width="50" Height="20" HorizontalAlignment="Left" VerticalAlignment="Bottom" Margin="5,0,0,0" />
            <RadioButton x:Name="rb2a" GroupName="Grp1" Content="no" Width="50" Height="20" HorizontalAlignment="Left" VerticalAlignment="Bottom" Margin="5,0,0,0" />
        </StackPanel>
    </Grid>
</Grid>
erControl>

The output looks like this (adjusted to save space)

twoGridsWithThemes

Note that the theme is in the .dll and not in App.xaml; you are certainly free to add styles and templates on top of these themes. 

As noted this micro-tutorial is only intended to get you started, and not to be comprehensive. Hope it helps.

Posted in z Silverlight Archives | Comments Off on Toolkit release & Themes

Greetings From PDC – Get Ready….

PDC is a wonderful conference but get ready for the onslaught of announcements, new material, information overload…

pdcbrain

I can assure that there is a lot of great stuff, and of course Tim and I and many others will be focusing on those announcements big and small that affect Silverlight.  This is a good moment, just a days before ScottGu’s keynote to say that it is our goal that Silverlight.net will prove itself as the go-to-first location to learn about everything new affecting Silverlight development.

We’ll be working closely with all the teams to make sure that we have the complete information and that we can offer mini-tutorials right away in our blogs, and well developed videos and tutorials in record time.

Since I’m in “pitch” mode, this may be a good time to consider subscribing as well so as not to miss anything. 

 Subscribe in a reader

Stay tuned, I’ll have lots of detail very soon.

Posted in z Silverlight Archives | Comments Off on Greetings From PDC – Get Ready….

So Much Technology – So Little Time

 

 

We have, I think, officially passed the point where anyone can keep up with the new technology available for developers, just from Microsoft (let alone all the new options from all the other companies), and PDC is les than a week away.

A  totally indefensible distortion of recent history as I remember it

When I started fussing with computers (1971) you could certainly learn the entire field (and then some) in a couple hours.  I was incredibly lucky, and I didn’t like it much (my friends who did like it are all stuck in jobs in banks working in Cobol or worse) and so I didn’t return to it with any seriousness until 1984). 

In the early 80’s you could teach yourself all there was to know about microcomputers, and you could come up the learning curve as you remained productive.

There were choices to be made (I distinctly remember choosing DOS over CP/M and then PC over Apple IIe and then DOS over OS/2 and then Unix/C over DOS (for practical reasons – I had a gig).  So by 1989 or so I was already “specializing.” 

In 1992 I was offered the opportunity to switch to Windows, which by then had grown up enough to be interesting. The project was cross-platform (Win 3.1/Mac; using a beta of the the ill-fated Bedrock cross-platform compiler) and, most important, it was C++, a switch I was eager to make and one which launched my 2nd career as a hack author (first book, 850 pages, 6 weeks; while working full time. Yowza!)

As an aside to this tangent, I’ll tell you that you have not lived until you try to create software with a new programming model (Object-oriented) on a beta development platform (Bedrock) with a beta compiler (Zortech) and an alpha debugger using a 3rd party editor;  none of which was designed to work with any of the others. We spent a couple years on that project (written about Beginning Object Oriented Analysis and Design) only to be eaten alive by the World Wide Web as well we should have been.  But I digress.

In any case, in the 1990s something else began to happen, not only did I find myself choosing one platform over another (Windows over OS/2 for example [“OS/2 version n+2, the Real OS/2”] – I found myself whittling down what parts of Windows I would spend my time learning, as Windows Development itself was getting to big to learn it all.

Just keeping up with my little niche was a full time job. Since about 1995: ASP –> Web Classes –> ASP.NET –> ASP.NET w/Ajax –> ASP.NET/AJAX/MVC…  .NET –> .NET 2, 3, 3.5., MFC ->  WinForms –> WPF –> Silverlight…. you get the idea.  (I confess, I just more or less ignored DCom, waiting patiently for it to go away). 

MacBookProAlong the way I’ve flirted with the Mac (I do like the Mac a lot and wish I’d spent more time there..  though on balance, so far it appeals to my tin man, not my scarecrow)    — but Silverlight meets that need, and I’ve convinced my boss that one of my “commitments” for this year is to increase my expertise in the Mac so as to provide cross-platform expertise (read this as: I get to play with my mac more).

Another aside: after 9/11 my rant was this: if I were in charge of the FAA the first thing I would do would be to call the Israeli Government and say “send me the person who set up your El Al security system, I want him in charge of the TSA for 1 year.”  Similarly, if I were in charge of Windows, the first thing I would do is hire packgagingsomeone whose full time job it is to be able to answer the question “why is this easier on the Mac?”  — it may be there are very good reasons, but we’d better know them.  Have you set up a Mac?  It is a blast.  Plug it in, wait a minute, answer two or three very obvious questions, wait a minute, you’re done.  

While I’m ranting, I’d also have someone on my team in charge of “why does their packaging look nicer than ours?”

</Rant></Digression>

Where Was I? Oh Yes…

I’m often asked how to evaluate Silverlight against Flash, and as I’ve said before, I don’t do that, (though there are lots of folks here who do that well). But the question that does interest me is this: of the ever increasing bounty of developer technology coming out of Microsoft: what do you need to know?

What Does A Silverlight Programmer Need To Know?

Let me start off by saying that this list will probably need to be updated frequently – not much I can do about that. Second, much depends on what else besides being a Silverlight programmer you have in mind, and what kinds of Silverlight applications you’ll be building and what size team you’re on and …. you get the idea.  Further, this is just my opinion – not a Microsoft official guideline.

That said, if I were pressed to answer what skills a Silverlight programmer really needs to keep up with, my list would start with:

Tools

Start here, return to here, this is critical.

  • Expression Blend and here
  • Silverlight

    Related Technology

    • Astoria
    • C# or VB (make your life easier)
    • Basic UI Design
    • WPF (Older sibling, many resemblances)
    • WCF (web services)
    • The Rest of .NET 3.5 Services (the mischpacha)
    • ASP.NET  (“Might be fun, could be dangerous, maybe tomorrow”)

    Some Books That May Help

    Knowing the author and his writing, my guess is that this will be terrific (not yet released)

    Data and Services with Silverlight 2: John Papa: Books

    ISBN: 0596523092
    ISBN-13: 9780596523091

    There are a number of good books on C# and VB. If you are new to both, I can’t help but recommend this, though this new edition won’t be out for a few weeks.

    Learning C# 3.0: Jesse Liberty, Brian MacDonald: Books

    ISBN: 0596521065
    ISBN-13: 9780596521066

    Books I like on learning the related .NET 3.5 technologies (yes, there i go again with one of my books, but it is the only one I know of that covers WPF, WCF, WF and all of .NET 3.5 in a single volume).

    Programming .NET 3.5: Jesse Liberty, Alex Horovitz: Books

    ISBN: 059652756X
    ISBN-13: 9780596527563

    Programming WPF: Chris Sells, Ian Griffiths: Books

    ISBN: 0596510373
    ISBN-13: 9780596510374

    There are a number of excellent books on ASP.NET, many from my own team…

    Posted in z Silverlight Archives | Tagged | Comments Off on So Much Technology – So Little Time

    November 22, 2008

    November 22, 1963.  45 years.  Sic Transit Gloria Mundi

    Posted in z Silverlight Archives | Comments Off on November 22, 2008

    It Ain’t You, Babe… A Not-a-bug bug in DataGrid

    SLLogoWords

     

    I’ll be writing a set of mini-tutorials on the DataGrid that will, as the King advises, begins at the beginning, goes on till it comes to the end and then stops[1], but before I do, a "Set Of Behaviors That Is Perfectly Understandable But Not At All What The Programmer Expects (SOBTIPUBNAAWTPE)" has surfaced in DataGrid.  (I was told this is not a bug – my response was a bit snide).

    Since this is causing a great deal of frustration and confusion, I wanted to alert you to it before you pull all your hair out – I’ll also let you know as soon as I have the details of the work around.

    iStock_ ice create spilled Large

    To understand the bug (oops) you need to understand two properties associated with DataBinding Validation for two-way binding.

    In English that means that when you enter data that will be written back to the data source, Silverlight will validate the data and handle two types of exceptions for you if you set the right properties.  The two types of exceptions are:

    1. Exceptions that are thrown when the binding engine tries to convert the type of the data
    2. Exceptions that are thrown from within the binding object’s set accessor

    The two properties that you need to set are NotifyOnValidationError and ValidatesOnException.  They both default to false. You want to set them to true; if you do the exceptions are turned into BindingValidationError events – and even better they are bubbling events which means that you can put your event handler on the containing control. 

    The way this is supposed to work is that you can associate an event handler for the BindingValidationError with the DataGrid itself, and if there is a problem binding the data in any of the columns it will bubble up to that one handler, rather than firing an exception that might bring your application to a stand still. 

    As a practical test of this, and stealing borrowing from examples from Reid Maker (who pointed out the SOBTIPUBNAAWTPE in private correspondence) and from Manish Dalal’s Blog (who illustrated how this should work during Beta 2) I tried to prove to myself that it wasn’t a bug by trying various variations (e.g., moving the event handler in and out of Xaml, moving the exception generation in and out of an event, generating the exception in each of the two ways, and so forth).

    Here is the code, somewhat simplified

    The Data Source Class

    using System;
    using System.ComponentModel;
    
    namespace DataGridBindingValidationTester
    {
       public class TestData : INotifyPropertyChanged
       {
          public event PropertyChangedEventHandler PropertyChanged;
          private int id = 0;
          private string name = string.Empty;
    
          private void NotifyChange( String name )
          {
             if ( PropertyChanged != null )
             {
                PropertyChanged( this, new PropertyChangedEventArgs( name ) );
             }
          }
    
          public string Name
          {
             get { return name; }
             set
             {
                name = value;
                NotifyChange( "Name" );
             }
          }
    
          public int Id
          {
             get
             {
                return id;
             }
             set
             {
                if ( value == 9 )
                {
                   throw new Exception( "can't have 9" );
                }
                id = value;
                NotifyChange( "Id" );
             }
          }
       }
    }

    Page Xaml

    <UserControl x:Class="DataGridBindingValidationTester.Page"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
        Width="400" Height="300" xmlns:data="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data">
        <Grid x:Name="LayoutRoot" Background="White">
            <Grid.RowDefinitions>
                <RowDefinition Height="0.15*"/>
                <RowDefinition Height="0.85*"/>
            </Grid.RowDefinitions>
            <TextBlock Margin="18,8,56,8" x:Name="Output" FontSize="14" Text="Error Messages Show Here" TextWrapping="Wrap"/>
            <data:DataGrid x:Name="TestDataGrid" Margin="10,10,10,10" Grid.Row="1"  AutoGenerateColumns="False" >
                <data:DataGrid.Columns>
                    <data:DataGridTextColumn Header="Name" Binding="{Binding Name}"  />
                    <data:DataGridTemplateColumn Header="ID">
                        <data:DataGridTemplateColumn.CellTemplate>
                            <DataTemplate>
                                <TextBlock  Text="{Binding Id}"  />
                            </DataTemplate>
                         </data:DataGridTemplateColumn.CellTemplate>
                        <data:DataGridTemplateColumn.CellEditingTemplate>
                            <DataTemplate>
                                <TextBox Text="{Binding Id,Mode=TwoWay,NotifyOnValidationError=true,ValidatesOnExceptions=true}" />
                            </DataTemplate>
                        </data:DataGridTemplateColumn.CellEditingTemplate>
                    </data:DataGridTemplateColumn>
                </data:DataGrid.Columns>
            </data:DataGrid>
        </Grid>
    </UserControl>

    Page.xaml.cs

    using System;
    using System.Collections.Generic;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Media;
    
    namespace DataGridBindingValidationTester
    {
       public partial class Page : UserControl
       {
          public Page()
          {
             InitializeComponent();
             Loaded += new RoutedEventHandler( Page_Loaded );
             TestDataGrid.BindingValidationError += 
                new EventHandler<ValidationErrorEventArgs>( TestDataGrid_BindingValidationError );
          }
    
          void TestDataGrid_BindingValidationError( object sender, ValidationErrorEventArgs e )
          {
             if ( e.Action == ValidationErrorEventAction.Added )
             {
                ( (Control) e.OriginalSource ).Background = new SolidColorBrush( Colors.Red );
                Output.Text = "Error: " + e.Error.Exception.Message;
             }
             else if ( e.Action == ValidationErrorEventAction.Removed )
             {
                ( (Control) e.OriginalSource ).Background = new SolidColorBrush( Colors.White );
             }
    
          }
    
          void Page_Loaded( object sender, RoutedEventArgs e )
          {
             List<TestData> tests = new List<TestData>();
    
             tests.Add( new TestData { Id = 1, Name = "A" } );
             tests.Add( new TestData { Id = 4, Name = "B" } );
             tests.Add( new TestData { Id = 2, Name = "C" } );
             tests.Add( new TestData { Id = 5, Name = "D" } );
             tests.Add( new TestData { Id = 3, Name = "E" } );
             tests.Add( new TestData { Id = 8, Name = "F" } );
             tests.Add( new TestData { Id = 7, Name = "G" } );
             TestDataGrid.ItemsSource = tests;
             
          }
       }
    }

    The key to why this should work is that the DataGrid’s Cell Editing Template for Binding the ID (when the user is entering data) has a DataTemplate that uses a TextBox that is bound with both of the necessary properties,

    <DataTemplate>
        <TextBox Text="{Binding Id,
                        Mode=TwoWay,
                        NotifyOnValidationError=true,
                        ValidatesOnExceptions=true}" />
    </DataTemplate>

    In addition, the event handler is created in the class constructor and implemented in the code behind.

    TestDataGrid.BindingValidationError += 
       new EventHandler<ValidationErrorEventArgs>( TestDataGrid_BindingValidationError );
    
    void TestDataGrid_BindingValidationError( object sender, ValidationErrorEventArgs e )
    {
       if ( e.Action == ValidationErrorEventAction.Added )
       {
          ( (Control) e.OriginalSource ).Background = new SolidColorBrush( Colors.Red );
          Output.Text = "Error: " + e.Error.Exception.Message;
       }
       else if ( e.Action == ValidationErrorEventAction.Removed )
       {
          ( (Control) e.OriginalSource ).Background = new SolidColorBrush( Colors.White );
       }
    
    }

    The bug is that this does not work.  The reason this is not a bug but a SUBTIPUBNAAWTPE is this: what is actually causing this to fail is not that the event wouldn’t be raised, but rather that by the time the error might be raised, the DataGrid has already shifted back from TextBox to TextBlock – and the properties are no longer set.

    (Okay, my snide answer was this: …it may not be a BindingValidation bug, but it is a Silverlight bug by any reasonable definition; or it is like saying that it isn’t a bug when your brakes fail because they were never really designed to stop the car if the car is on an actual road, though they work just great up  on the lift.  )

    More about this soon…. including a much more systematic review of DataGrid.

    [1] Alice in Wonderland – Public Domain – Project Gutenberg

    Posted in z Silverlight Archives | Comments Off on It Ain’t You, Babe… A Not-a-bug bug in DataGrid

    Sizing in Silverlight – Pixels and Stars

    SLLogoWords

    Virtually all measurements (width, height, etc.) are measured in Pixels in Silverlight… except when they’re not.  

    Pixels

    When you are creating a shape or setting a margin, or filing in the width or height of a control the implicit unit is pixel.  Thus,

    <Button  Content="Button" Width="100" />
    <CheckBox  Content="CheckBox" Height="20" Width="75"/>
    <StackPanel Orientation="Horizontal" >
        <RadioButton Height="29" Width="106" Content="RadioButton1" />
        <RadioButton Height="29" Width="136" Content="RadioButton2" />
    </StackPanel>
    <ListBox Width="100" Height="100">
    </ListBox>
    <Slider Width="250" Height="25"/>
    <swc:Calendar Height="150" Width="200" />

    All the measurements here are pixels, from the width of the button to the height of the Calendar.

    Proportional (Star) Sizing

    There are two ways to set the height of a grid’s row or the width of a grid’s column. One is to use absolute sizing, and thus pixels; the other is to use proportional sizing. When you create a pair of rows by clicking on the margin in Blend, the default is not to create two rows with absolute sizes, but rather two rows whose size is defined relative to one another.  This is indicated in the art board with open locks and in the Xaml with asterisks after the height values.

    GridProportionalSpacing

    When row and height values are expressed using star sizing, the unit of measure is not pixels; they are proportional values. Thus, Blend has indicated that the top row is to be allocated 25% of the total height and the bottom row 75%

    If you click on both locks, you’ll change over to absolute heights, the locks will close, and the Heights will become 120 and 360 (no asterisks) respectively; now measured in pixels, but in the same proportions.

    Pop Quiz

    One of these things is not like the others:

    <Grid.RowDefinitions>
        <RowDefinition Height="0.25*" />
        <RowDefinition Height="0.75*" />
    </Grid.RowDefinitions>
    
    <Grid.RowDefinitions>
        <RowDefinition Height="100*" />
        <RowDefinition Height="300*" />
    </Grid.RowDefinitions>
    
    <Grid.RowDefinitions>
        <RowDefinition Height="100" />
        <RowDefinition Height="300" />
    </Grid.RowDefinitions>

     

    -jesse

    Posted in z Silverlight Archives | Comments Off on Sizing in Silverlight – Pixels and Stars

    Silverlight and Data

     

     

    Tim and I and many others have been discussing, off and on, the frequent requests for videos/tutorials/demos, etc. that show how to move data into and out of databases and display them in Silverlight.

    On the one hand, my response is that the very question reveals that we’ve not done a good enough job explaining the boundaries of Silverlight as a UI tier-framework; that once you’re talking about creating (rather than consuming) a web service and once you’re writing LINQ you are outside of Silverlight.

    On the other hand, I see two compelling counter arguments.

    #1 is that by showing the complete set of tiers and how they interact (SQL and whatever technology we choose to get the data in and out (e.g., Linq or  Astoria) and WCF to create a web service, and Silverlight consuming the web service, probably creating business objects, and a DataGrid in Silverlight to display the data, along with two way binding, we better establish where the actual boundaries of Silverlight lay and how Silverlight interacts with these other technologies.

    iStock_EngineXSmall

    #2 is that for most of our readers Tim and I may be “Silverlight Developer Community Program Mangers” but really we’re just Microsoft techies. And as I wrote in a private correspondence “when I go into my Subaru dealer, I understand that one guy may be a transmission specialist but that doesn’t mean he can’t answer a simple question about how frequently I should change my oil.  If I feel it is clear that the explanation I’m asking for will take sitting down and getting into details and really call upon his specialty that is one thing, but if it is just a general Subaru question, then his answering “oh, I don’t do oil”  would probably infuriate me and it certainly wouldn’t help me understand where the transmission system ends and the engine system begins and how they both form part of the powertrain.”

    So, after thinking about this quite a bit, I think we have to show the entire power train: from inside the SQL db through displaying it in a DataGrid, but with a clear emphasis on the Silverlight front-end and how and where you can learn more about the other enabling technologies for the other tiers.

    More to come, but I invite your feedback.

    -j

    Posted in z Silverlight Archives | Tagged | Comments Off on Silverlight and Data

    Something New Coming – Pocket MFA

    My theory, based entirely on my own experience is that many developers would like to know just a bit more about design (not all developers, and not a lot more, just some developers, and just a bit more). Our reasons include:

    1. The bar has been set higher by Silverlight and other application development platforms that set high user expectations

    2. Some of us don’t have access to professional designers, or don’t have access early in our project

    3. Some of us are developing prototypes and no designer is involved but we want the prototype to look good enough that the design doesn’t “get in the way.”

    In short, we’re putting our code in front of others, and while many folks can say they don’t care what it looks like, the truth is that good looking (or at least good-enough looking) code makes a very different impact than poor looking applications.

    Thus, I am taking action. My goals are to provide this information to developers in what I’m calling the Pocket MFA  series. This is an entirely optional set of add-ons to the tutorials, videos, blog entries and other work I do. It will be optional and easy to skip, but my hope is that you’ll find value in it. It is an experiment that will last through Q1 and then be reassessed.

    As a start, I’ll be making recommendations on some background reading, but I’m happy to announce that one of our best designers will be adding a brief commentary to my forthcoming videos (at the end so you can skip it if you really don’t want to know about this) detailing small changes that I could have made to improve the appearance of my application.

    These commentaries will run under 5 minutes, but collectively I hope to learn and I hope they will teach, the fundamentals that we can use to bring the appearance of our applications up that notch or two that can make a world of difference.

    There are three books that I typically state are indispensible to anyone creating software (The Design of Everyday Things, Why Software Sucks and Don’t Make Me Think).  That said, if we’re focusing on design, then I think we may want to start with this gem:

     

    And while it is not targeted at Silverlight 2, you may well want to get a leg up by watching Arturo’s brilliant video from the Fire Starter series. Click on the image below to go to the Firestarter site, and then click on Arturo’s tile (see arrows) to watch his video.

    FireStarter

    Posted in z Silverlight Archives | Comments Off on Something New Coming – Pocket MFA

    Liberty – Shill?

     

    Recommends2 Okay, I never thought this was an issue I was likely to face, but the folks in Marketing wanted to run this ad, and so I was faced with that interesting question of what we used to call “Selling Out.” (yeah, yeah, i work for Microsoft, so my radical friends would say that happened long ago!)

    And, actually, that was how I decided it was fine (and very ego enhancing I admit). That is, I work for Microsoft, and specifically in this job, because I don’t have to say anything I don’t believe; and this ad doesn’t ask me to say anything I don’t believe, and wouldn’t say – in fact I say it all the time. (In fact, come to think of it, I’m not getting paid for the ad so how can this be a sell out?  Hey! I wanna sell out, please?)

    I do recommend Expression Blend, heartily and with no hesitation to anyone writing Silverlight applications. In fact I did a video, Green Eggs and Blend on “why I gave up a 15 year commitment to working in a single Integrated Development Environment and came to discover I do so Like Expression Blend.”

    But…. since it is weird, I thought I’d post about it. Of course the biggest reaction may not be “how could you?” but rather, “who cares?”  That said, to the extent that anyone does; I thought I’d say out loud that here, as with Silverlight, C# and etc.; the enthusiasm comes before the recommendation, job, book or whatever.

    The picture of me, by the way, is by Rachel Liberty; age 12.  Nice shot.

    Posted in z Silverlight Archives | Comments Off on Liberty – Shill?

    Did You Try to Attend A WebCast Today??

     

     

    Apparently a Web Cast cancellation sent out months ago did not reach some 34 loyal, innocent and now very frustrated users; to whom I sincerely apologize.

    iStock_SadGirlverySmall

    It was not my intention to leave you in limbo; in fact I didn’t even know about the meeting until I received an email from one or two folks asking if something went wrong (nice of them to give the benefit of the doubt). There are no excuses, except to say that we tried carefully to inform everyone many weeks ago when we changed the schedule.

    There are two webcasts left on the schedule

    • Skinnable Custom Controls on November 12
    • Deep Zoom on December 17

    After that, I’m going to pull back from Webcasts and think long and hard about how to use that medium more effectively.

    In any case, if you were there, waiting, and wasting your time, I do apologize, and if you drop me a line and let me know, I’ll see if I can’t get you a pass to the on line version of Programming Silverlight once we’re up on Safari as my way of apologizing.

    Posted in z Silverlight Archives | Comments Off on Did You Try to Attend A WebCast Today??