Page view counter

July 2009 - Posts

Turing Project: Two Levels

Turing Entry: [Novice: 2]  [Advanced: 2]    FAQ     Table of Contents    

 

In a previous post I described Project Turing. This is the second entry for that project and will describe how I hope to meet the needs of two audiences: 

Novice: programmers who may or may not have experience with other languages, may not know C# (or advanced C#), .NET or the fundamentals of Silverlight (e.g., what Xaml is)

Advanced: programmers who have worked with Silverlight and want to go beyond the basiscs; who want to see a design-to-delivery walk through that touches on more advanced topics.

You Can’t Get There From Here

In traditional publishing, I couldn't possibly address both audiences in the same documentation. Either I would lose the novice by assuming to much, or I would make the advanced  programmer crazy by explaining too much.

But the web is different. I believe that I can document the entire process of design-through-delivery of Project Turing for both audiences independently, but in a single set of posts

(I don’t think anyone has tried this, but I do think it can be done and if done well, would be valuable. In any case, it will be fun to try.)

Follow the Yellow Brick Road

I was in a very large hospital not long ago. At the information desk you could look up and see 8 colored tubes. You told the desk person where you wanted to go and they handed you a piece of paper with one of the 8 colors.   Just follow your color.  As you walked along, the different colors would branch off… sometimes they’d rejoin for a while. If you kept an eye on your color, the tubes took you where you wanted to go.

This project will be documented with two tubes, er, threads: Novice and advanced. You just follow your thread

iStock_ 3 elevators Large


Every entry will have a pointer to the next and previous entry for both threads. If you follow a single thread it should read like a continuous story,but of course you are free to switch back and forth as your interest dictates.

 

Not Sidebars, Not Asides; A threaded Whole

What you end up reading should not be a set of side-notes, but rather a coherent set of posts and tutorials, targeted at your level of experience.

Let me be very clear about my objective as it is unusual:  If you choose to follow the Novice path , you should experience that you are reading a Novice-targeted  set of posts, not an advanced set of posts with asides for beginners.

Headers, Footers and “Page numbers”

Beginning with this post, and for the rest of this project, each blog posting on Project Turing will bear a header much like this:

 Turing Entry: [Novice: 7]  [Advanced: 3]    FAQ     Table of Contents    

You read the header shown as follows: “This is the 7th entry for the Novice thread and the 3rd entry for the Advanced thread.  

[What you are reading right now, however, is the second post for both]

At the bottom of each page you’ll find a footer like this:

[Novice]       Previous    Next
[Advanced]  Previous    Next

by following the Next for your thread you should find that the entries are numbered consecutively. Thus you can think of the series as looking like this:

 

TuringPageNumbers

 

[This posting was updated and clarified on 8/6]

------------------

[Novice]       Previous    Next
[Advanced]  Previous   

 

Bayesian Probability (Quick Bit)

Added a Quick Bit today on Baysian Probability.

Posted by jesseliberty | with no comments

AgOpenSource Project Turing

 

 Turing Entry: [Novice: 1]  [Advanced: 1]    FAQ     Table of Contents    

ProjectTuringLogo

I’m very pleased to announce the launch of a new AgOpenSource project, code named: project Turing.

The Turing project will prototype a fully automated web service and Silverlight Front End for the display of any blog entry* that discuss Silverlight programming skills.

*Current design constraint is Microsoft employees only.

 

 

Functional Design

There will be three core modules

1. Data Entry

The goal is to lower the barrier to data entry. Eventually we’ll want to support all of the following (and more) for sending in the information required to be listed

  • Email using a fast simple syntax or a template
  • A web site
  • A plugin for LiveWriter
  • etc.

 

EmailDataEntry

 

2. DataBase and Web Service

The second part of the design calls for the storage of the information in a SQL Database and the retrieval of that information through a WCF Web Service.

 

3. Silverilght Application For Display

The front end to the application is a Silverlight data grid that allows the user to sort and otherwise customize the display.

 

BlogProject

 

 

[updated 8/4/2009]

 

Next: Turing Project Levels

Posted by jesseliberty | 19 comment(s)
Filed under:

Video Wiki – Status and Overview

This page will serve as the Overview of the VideoWiki Application to be developed as part of the AgOpenSource project. This particular application is on temporary hold pending its move to Moderated Open Source as of July 30.

Definition

VideoWikipedia, videoWiki and ViKi all refer to the same concept, initially conceived in April of 2009. A videoWiki is a hyperVideo whose links are not fixed, but rather are determined by associating the video with one of potentially many sets of link sets.

In many ways, a videoWiki is best understood as a HyperVideo with interchangeable links. A normal HyperVideo has specific links associated with various  scenes or events in the video, or with a specific location in the video.  When you follow the link you may be taken to additional information or even to another video.

A video created for a videoWiki does not have links at specific scenes or events, rather it typically has very frequent links added at regular intervals (e.g., every 10 seconds) that have no inherent meaning but serve as potential link points for the creator of the Viki.

To be clear: the creator of the video does not presume in advance to know what the creator of the links will want to link to! In fact, the very nature of a videoWiki allows for there to be many link creators.

With a videoWiki , the set of links and where they take you are uncoupled from the video, and you may choose from a variety of links for any given video.

For example, imagine that when you choose a video on Creating Out Of Browser applications in Silverlight 3, and you are offered to watch it in our (not yet created) videoWiki player. If you agree to do so, you are then asked which link set of video links you would like:

1. Links targeted at programmers new to Silverlight

2. Links targeted at experienced programmers

3. A link set created by <famous author>

4. A link set for those who like extremely technical commentary

Once you make your choice, you load your video and your link set, and as you watch, text with links slowly scrolls by  in a window next to the video. If you click on a link, the video pauses, and a new video opens with additional information.

The links you see with the video may be quite different from the links I see if we choose different link sets

History & Background Information

Some preliminary work has been done, here are links to those entries:

 

For background, you will also want to read the mini-tutorial thread on HyperVideo and take a look at the related videos.

 

Hypervideo Videos

Posted by jesseliberty | 5 comment(s)
Filed under: ,

AgOpenSource Moves Forward

.

Our Goal Is Not To Create Great Programs;
It Is To Create Great Programmers

 

This posting will quickly review the AgOpenSource project, whose Table of Contents is available at www.AgOpenSource.com or from a link on the sidebar of my blog.

Overview

Note: this overview is an excerpt from the home page of AgOpenSource

AgOpenSource is, at its heart, an experiment in moving from from stand alone demonstrations of specific Silverlight skills to exploring the breadth of Silverlight by implementing applications from design to testing.

By its nature, this project will experiment with a number of different approaches. That said, there have been some false starts leading up to the current incarnation, and it is my goal for there to be some stability in the project for the rest of 2009.

I will be updating the AgOpenSource project  on a weekly or semi-weekly basis for the rest of the year.

Multiple Applications, One Project

AgOpenSource.com  has settled into a on-going and active project which will serve as an umbrella for a number of applications that will be developed under one of two approaches that I have named

  • Glass House
  • Moderated Open Source

Glass House

Glass House Projects are those which I will develop documenting my thinking and work from inception through delivery but which the community will contribute to only through comments and suggestions. By accepting this limitation I am able to move forward very quickly without needing to secure open source licensing.

Every week or two the Glass House application will spin out videos, mini-tutorials and so forth, complete with source code and the goal of these applications will include:

      • Providing Silverlight Skills videos and mini-tutorials
      • Insight into evolving best practices
      • Potential prototypes for further development

Moderated Open Source

Moderated Open Source applications will be developed much like Glass House applications, except that members of the community will be offered, if they choose, the opportunity to contribute modules, alternatives, code, etc., to the project under a license to be finalized in which their code is provided to the project and for which the contributor will be acknowledged but the code will be open to modification both for integration into the project and for use in demos, videos, etc. (Details to follow)

CodePlex

It is my goal that the Moderated Open Source applications will migrate to CodePlex at the earliest opportunity; I am working this issue actively and will have progress, I hope, by early August.

 

Getting Started

For information on the first two applications to be developed, please see the Table of Contents on the AgOpenSource Home Page.

Pace of Development

I will be devoting 2 or more days per week to the AgOpenSource project, and expect to be adding both progress notes and videos/mini-tutorials as a result at a rapid pace beginning today. It is my hope that there will be active feedback from the community on many levels, including but not limited to:

  • Questions and follow up
  • Corrections and bugs found
  • Alternative approaches considered
  • Suggestions for features, design, approach, architecture, implementation, etc.

OMG, where do I start?

A lot of email comes my way beginning with the sentiment: “I’m not sure who to ask, and you’re the Silverlight Geek, so….”  Which is great.  I often refer them elsewhere, but it gives me a sense of what is on people’s minds, and also how well we’re doing making it obvious where the answers are.

The site redeisgn helps a lot (you’ve seen our new site, right?) but with this much information available, and this rapidly changing a product, it can be very difficult to find exactly what you need, especially if you are approaching things from a problem-specific vantage point.  We’re working on these issues, and more on that to come.

In answering this person’s question, however, I realized that there was some generalizable advice about how to get started and find what you need that it made sense to blog about. 

How Do I Accomplish This In Silverlight?

That simple question can have an answer as short as “Go look at this video where we do something very similar and then download the code and modify it” and as long as “here are the 20 things you need to learn before you can try to do that…..”  This is all made more complex because virtually every user brings a different level of experience, domain expertise, and confidence to the table.

That said, there are some general pointers that we (here at Microsoft) need to get out as often as we can.

What Is Your Real Goal

That is the first question you have to ask yourself and that anyone offering you advice should be asking.  As they say, you can’t get there if you don’t know where you want to go.

To simplify greatly, I usually see one of four goals (or something along the spectrum, in any case)

1. I want to create an application that does this and I want to do it fast, and not learn anything else; tell me how to get this done.

2. I need to create an application that does this, and along the way I’ll pick up some useful and reusable skills

3. I’d like to learn Silverlight (or Expression or….) and to do so I’ll build this to keep me focused

4. I have no idea where to start, but this sure looks like fun.

What Do You Know,
What Are You Willing To Learn,
and How Much Time Do You Have?

Let’s take an easy case: you are not a programmer and you don’t want to be one, you don’t have that much time and you want to learn only enough to get your job done.  this case is easy because my advice is straight forward: be the domain expert: hire the programmer.  If what you want to do is not trivial, then you’re going to fall into the Prime Directive of coding:

Easy, Fast, Good: Pick Any Two

So, let’s back up and assume that you are not case #1 (Starting from scratch, don’t want to learn to program, want to get there fast)  because I believe the idea of that person writing a meaningful program that will satisfy their requirements of commitment, time, etc. is a non-starter.

For the other three cases, much depends on where you start out.  The spectrum ranges from experienced .NET programmers to total novices.  Suffice to say that the speed with which you’ll pick up Silverlight Programming is a stochastic outcome of talent, experience, luck and effort.

So what to do?

Rather than mire ourselves in the myriad approaches people take, let’s simplify this to the big 3:

  1. Buy It
  2. Learn from the bottom up
  3. Learn from the top down

#1 is not to be disparaged; in the build/buy decision many a programmer has burned a lot of their client’s money out of an insistence on building that which could be bought more inexpensively and with more reliability.  But let’s set that aside for this discussion.

Top Down vs. Bottom Up

I’ll define these as follows (and let’s not quibble about corner-cases)

Top Down – Learn Silverlight by starting with what you want to build and learning how to build that – learn just enough  of each skill to build your product.

Bottom Up – Set your project aside, learn the core skills, then look to combine them to successively approximate your project.

Of course, very few thoughtful people will take one approach to the total exclusion of the other but it is startling how many folks really try the Top Down approach. 

I’m pretty sure some folks succeed with Top Down,  but I’ve never seen it.

Boot Strapping

That doesn’t mean you have to learn everything about everything before you can do anything about anything, but it does mean that There Still Ain’t No such Thing As A Free Lunch.

Now, back in the dark ages, when I was moving from hacking to coding for cash, you could still learn everything there was to know about programming a PC in a couple weeks or months (and then about a year later, realize you were wrong, but that too is another story).

Today, you’re going to have to pick and choose, and what you pick and choose will be determined by your interests, goals and curiosity ,but it should be guided and informed so that you don’t “waste” a lot of time (as if learning something is ever a waste).

A Focused Course Of Study With A Little Help From Your Friends

Here’s the good news, I’m convinced you can learn to program Silverlight much more quickly than you might expect, if someone provides bread crumbs for you to follow.  So I’ll have a go at providing an example of what I mean.

The person who wrote to me (remember him?) wanted to create an application that I will modify into the following spec. Start by taking a look at this graphic (click on the image to make it larger:

TM_qtr_py_category[1] 

This amazing image was created by Mike Hendrickson; Senior Editor at my publisher, O’Reilly Media,  to reflect trends in the technical book market. Here’s Mike’s explanation:

The size of a square shows the market share and relative size of a category, while the color shows the rate of change in sales. Red is down, and green is up, with the intensity of the color representing the magnitude of the change. [This image] shows gains and losses by category, comparing the fourth quarter of 2008 with the fourth quarter of 2007.

You can certainly build this in Silverlight, you can make it wicked cool, and you can make it even better by adding, for example, animation that lets the user click on a box and have it flip over and provide more detail, by adding animation to indicate change over time, and in many other ways. 

But it is non-trivial.

How To Build This?

If, like today’s writer, you were to tell me that you have all this data, and you have this vision but you are not a programmer, I would suggest two approaches that might work well:

1. Hire someone who is a solid Silverlight Programmer to code it for you or

2. Plan to learn a good bit of Silverlight and Expression before tackling this.

Assuming you chose option 2…..

A Road Map

I would recommend that you accept that you do need certain fundamentals, but not all of them. With guidance, you can choose to learn some relatively advanced material before mastering some relatively introductory material, as long as you choose well.  Thus, I might suggest:

1. Pick a language (C#, VB, IronRuby, etc.).  Do not discuss this with anyone as you’ll start a religious war that will lead to great suffering of innocents.  Just pick one. It almost doesn’t matter which you pick. I tend to use this algorithm: 

 
Langguage whichLang = null;
 
while ( PickALanguage(randomChoiceGenerator) != C# )
{
   continue;
}
 

Assuming, somehow, you picked C#, find a decent introductory book. There are many good choices, here is one at random…

Learn the following topics even if you can’t see how they relate to what you want to do:

  • Visual Studio
  • Language Fundamentals
  • Operators, Branching
  • Object Oriented Programming
  • Classes, Methods
  • Lists, Generics
  • Interfaces and possibly Exception Handling

Learning Silverlight and Expression

Then set that aside and get a good book on Silverlight and another good book on Expression Blend and start working through those. At this point, you’ll also want to start taking advantage of the resources that are available on our sites, such as Videos and mini-tutorials about specific techniques, mini-tutorials, etc.

Find a community where you can get your questions answered: a great starting place are the forums on Silverlight.net and on the Expression Site and be sure to subscribe to Silverlight Cream – a daily edited compendium of the very best blog entries. 

All this is daunting, and I’m looking at a very accelerated course!  The simple reality is that Silverlight programming can be your first programming language/platform, but it won’t be trivial. 

How Long Will It Take?

How long will it take for me to get in shape? For Joe  to learn to sing? Much depends on motivation and talent, but realistically, I would think that someone working at this with some effort, who is pretty bright, could learn enough to build that application in 3-9 months (a bit of a range, eh?)  Some will depend on how much help they can get.

The Good News

The good news is that the more you already know about programming; Windows; .NET; Silverlight; Design etc. the shorter the learning curve, and the even better news is that you can do all this for free using the resources on Silverlight.net and its sister sites.

Good luck, and when in doubt, use the forums; they are the single most powerful way to get questions answered quickly and with some authority.

What’s New In Silverlight 3 – Navigation

As Silverlight moves from providing controls and UX bits to providing a framework for creating entire applications, it becomes more important to have a framework for multi-“page” applications.  Silverlight 3 introduces the Silverlight Navigation Application

SLNav101

This template in Visual Studio creates a series of files that serve as a very flexible and customizable framework for multi-page applications. The unmodified user experience, out of the box, is shown in this live demo, followed by a brief analysis of the code that Visual Studio creates.

(Note that I did modify the size to fit this page.) Visual Studio creates the usual MainPage.xaml/...cs and App.xaml/...cs files but also creates an Assets folder, containing Styles.xaml and a Views folder containing three starter pages:
  • Home.xaml
  • About.xaml
  • ErrorWindow.xaml

Each with its own code-behind.

You’ll notice that if you click on about the page switches, while the frame around the page does not. 

Frame and URI Mapping

I’ll go into the details in an upcoming mini-tutorial and video, but the basic structure is that MainFrame.xaml provides an instance of System.Windows.Controls.Frame  (found in the d System.Windows.Controls.Navigation namespace).  The Frame supports navigation among pages, and also supports passing information to the page to tell it what state it should be in.

Rather than forcing you to provide a full path to the page, the Frame class allows you to request the page you want with an instance of URIMapping, which in turn provides support for parameterized URIs that request a page by mapping parameters to a full URI.

For example, your frame might contain a URIMapping that looks like this:

 

   1: <!-- snippet from the Silverlight Documentation -->
   2: <navigation:Frame.UriMapper>
   3:        <uriMapper:UriMapper>
   4:            <uriMapper:UriMapping 
   5:                Uri="/ProductDetail/{productid}" 
   6:                MappedUri="/Views/ProductDetail.xaml?ProductId={productid}"/>
   7:            <uriMapper:UriMapping 
   8:                Uri="/{pageName}" 
   9:                MappedUri="/Views/{pageName}.xaml"/>
  10:        </uriMapper:UriMapper>
  11:    </navigation:Frame.UriMapper>

You can see that this allows you to bring up a Product Detail page based on the provided ProductID and a second page based on whatever name is provided.

(full details and a complete walk through to come in the forthcoming mini-tutorial and video).

 

 

PreviousMerged Resources

What’s New In Silverlight 3 – Merged Resources

Silverlight 3 provides the ability to manage your various resources in dedicated files and folders, and then merge them together as needed. This allows for far easier scaling of applications and easier reuse of resources.

It is easiest to see this at work by creating a small example. I’ll open a new application and name it MergedResources1 and I’ll create this one in VB.

To keep life simple, I’m going to use some of the resources I used in the based-on-styles discussion. I’ll create a simple layout with three buttons:

   1: <Button x:Name="Button1"
   2:         Content="Standard"
   3:         Grid.Row="0"
   4:         Grid.Column="1"
   5:         Style="{StaticResource StandardButton}" />
   6:   <Button x:Name="Button2"
   7:         Content="Big"
   8:         Grid.Row="1"
   9:         Grid.Column="1"
  10:         Style="{StaticResource BigButton}" />
  11: <Button x:Name="Button3"
  12:         Content="Big Font"
  13:         Grid.Row="2"
  14:         Grid.Column="1"
  15:         Style="{StaticResource BigFontButton}" />
  16:  

These are inserted into a two column grid.  Notice that three resources are called upon:

  • On line 5 we look for the StaticResource named Standard Button
  • Line 10 looks for the StaticResource named BigButton
  • Line 15 wants the StaticResource named BigFontButton

The BigFontButton style, however, uses a new resource:

   1: <Style x:Key="BigFontButton"
   2:     TargetType="Button"
   3:     BasedOn="{StaticResource BigButton}">
   4:    <Setter Property="FontFamily"
   5:        Value="Georgia" />
   6:    <Setter Property="FontSize"
   7:        Value="24" />
   8:    <Setter Property="Background"
   9:          Value="{StaticResource bBrush}" />
  10: </Style>
On lien 9 we declare that a BigFontButton will use a brush whose key is bBrush. 

Breaking Resources Into Files & Directories

In a Silverlight 2 application all these resources would be in App.xaml. As you move to larger and more complex applications it helps greatly to be able to organize your resources into folders. This allows you to deal with smaller files that are more clearly dedicated to a specific purpose; and it fosters reuse.

You accomplish this in Silverlight 3 by creating a folder of your resource files, and then merging in each resource dictionary where it is needed.  In this example, I’ll create a folder named resources, and place two files into it:

Resources

I’ll put the brush into Assets.xaml

   1: <ResourceDictionary
   2:     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
   3:     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
   4:   <LinearGradientBrush x:Key="bBrush">
   5:     <GradientStop Color="Red" Offset="0" />
   6:     <GradientStop Color="Yellow"
   7:                   Offset="0.5" />
   8:     <GradientStop Color="Blue"
   9:                   Offset="1" />
  10:   </LinearGradientBrush>
  11: </ResourceDictionary>

I could of course create a set of brushes in this file. 

With that in place, I can create my stiles in Styles.xaml and when I want to use the Brush I just merge in the library…

   1: <ResourceDictionary
   2:     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
   3:     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   4:                     xmlns:vsm="clr-namespace:System.Windows;assembly=System.Windows">
   5:   
   6:   <!-- Merge in the Assets dictionary -->
   7:   <ResourceDictionary.MergedDictionaries>
   8:     <ResourceDictionary Source="Assets.xaml" />
   9:   </ResourceDictionary.MergedDictionaries>
  10:   
  11:   <Style x:Key="StandardButton"
  12:          TargetType="Button">
  13:     <Setter Property="Width"
  14:             Value="100" />
  15:     <Setter Property="Height"
  16:             Value="35" />
  17:     <Setter Property="HorizontalAlignment"
  18:             Value="Left" />
  19:     <Setter Property="VerticalAlignment"
  20:             Value="Bottom" />
  21:   </Style>
  22:  
  23:    <!--Based on style -->
  24:    <Style x:Key="BigButton"
  25:          BasedOn="{StaticResource StandardButton}"
  26:          TargetType="Button">
  27:       <Setter Property="Width"
  28:             Value="150" />
  29:       <Setter Property="Height"
  30:             Value="50" />
  31:    </Style>
  32:  
  33:    <!--Based on style that uses brush from Asset.xaml-->
  34:    <Style x:Key="BigFontButton"
  35:        TargetType="Button"
  36:        BasedOn="{StaticResource BigButton}">
  37:       <Setter Property="FontFamily"
  38:           Value="Georgia" />
  39:       <Setter Property="FontSize"
  40:           Value="24" />
  41:       <Setter Property="Background"
  42:             Value="{StaticResource bBrush}" />
  43:   </Style>
  44:  
  45: </ResourceDictionary>

 

You’ve seen the based-on syntax (lines 25 and 36) before; what is new here is merging in the dictionary defined in Assets.xaml (lines 7-9) and then using that resource on line 42. 

Root It In App.xaml

Styles.xaml brings in Assets, but we’ll use App.xaml to bring in Styles.

   1: <Application xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   2:              xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
   3:              x:Class="MergedResources.App">
   4:     <Application.Resources>
   5:        <ResourceDictionary Source="Resources/Styles.xaml" />
   6:   </Application.Resources>
   7: </Application>

 

Since App.xaml is brought in automatically, we now have it all.

 

Previous:  Multi-select ListBox    Next: Navigation

How Corporations Should Handle Mistakes

 

Every large corporation, sooner or later, is going to do something bone-head stupid.  It is the nature of people to make mistakes now and again, and if you aggregate people into a large organization that affects lots of other people, those mistakes will be bigger, bother more people and perhaps have more serious consequences.

We’ve lived through years of non-denial denials [“those statements are now inoperative”], equivocation “what the Senator meant was…”  and failure to take responsibility (“mistakes were made [passive voice]). It is totally refreshing to see a CEO take full and unequivocal responsibility for a mistake, and my bet is that by doing so Jeff Bezos just saved Amazon a great deal of time, money and aggravation, as well as loss of good will.



This is an apology for the way we previously handled illegally sold copies of 1984 and other novels on Kindle. Our "solution" to the problem was stupid, thoughtless, and painfully out of line with our principles. It is wholly self-inflicted, and we deserve the criticism we've received. We will use the scar tissue from this painful mistake to help make better decisions going forward, ones that match our mission.
With deep apology to our customers,


Jeff Bezos
Founder & CEO
Amazon.com

 

 


 

[Background, the week of July 13 Amazon deleted certain editions of Orwell’s 1984 and Animal Farm from user owned Kindles as they had been sold in violation of copyright. They credited the owners of the books for the cost, but many were surprised to learn that Amazon believed it had the right to remove books already on their Kindle. The irony that one of the books was 1984 was too precious to miss.

 

 

 

 

(Full disclosure, I am an Amazon Associate, and have been for some time.)

Posted by jesseliberty | with no comments
Filed under: ,

Preliminary Product Review – Blown Away by Xobni

NB: This post is not about Silverlight; it is a short digression to share one of the cooler new products I’ve seen.  Xobni Outlook add-on is so amazingly useful and fast and solid, you may really want to take a look at it. The product name is xobni (inbox spelled backwards) and it is an Outlook add-on.

It does a lot of stuff, but the biggest is wicked-fast retrieval of anything Outlook knows about – that is your contacts, your email, etc.  More important, it combines that information in truly useful ways.

 

xobni1a

 

Click for Details

Each pane can be expanded, contracted, closed, etc.

There are a number of icons that supply additional details or connections to additional services (e.g., Facebook).

Any conversation can be opened and the conversation pane allows you to see the back and forth and who participated.

 

xobni2

Note the slider for details, sliding it to the left shrinks down how much you see of each message, but you can hover over a message to see more

 

xobni3

 

Here I’ve shrunk the detail all the way down to a single line, but when I hover over David’s message out pops a window with the full text, above which it provides the message header. Nice.

 

Gotta Love Stats

There is something about the statistics that really grabs me, though I’m not yet sure of what practical use they are… though my manager might be happy that I’m seeing that in the past couple months I’ve sent him 150 messages and received half a dozen from him, indicating that I’m probably copying him in too many conversations. So maybe the stats will be useful after all.

 

xobni4 

There’s a good bit more to explore, but my  initial impressions were so strongly favorable that I decided to put this right into the main blog; I’ll link to this from my Reviews and Recommendations page and follow up once I’ve used the product for a while.

Inexpensive, But Pricing Structure Is Unfortunate

My only complaint so far is around price.  They bring you in for the freebie, but it is pretty seriously limited.  Their comparison chart indicates that you have to move up to Pro to get a number of features, the  most important of which (in my opinion) is searching by full text.

I have to say, full text search seems almost the sine qua non of this kind of product and makes the free version almost, but not quite, crippledWare. That said, the pro version does come with a year of support and no ads and is only $29.

While I think folks should charge the market-clearing price for a product, and structure their sales however they feel is best, as a consumer I don’t love that they charge an additional $10 per computer. A significant number of their early adopters are going to be geeks, and we tend to have a number of computers. Charging per cpu strikes me as a tough pill to swallow.  I’d like to seem them offer an alternative where one license can be used on three machines (for example) so long as the email accounts are identical.

 

Summary

The truth is I won’t know until I live with it for a while, but initial impressions are very positive. It seems like the kind of product you could learn to love, and since it was endorsed by WinZip (though I have no idea if they’re involved financially) I’m pretty optimistic.

If you try it, let me know how it works out.

What’s New In Silverlight 3 - Multi-Select List Box

n Silverlight 3 the standard ListBox now has a SelectionMode property which is filled from an enumerated constant whose possible values are

    •    Single
    •    Multiple
    •    Extended

When setting the SelectionMode Intellisense will display the potential values

 

MSListBox

 

Creating and using a multi-select list box requires only setting the property and retrieving the values. In the following example we create a multi-select list box, a button to indicate that our selection is complete, and a TextBlock to display the retrieved values,

   1: <UserControl x:Class="MultiSelectLB.MainPage"
   2:   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   3:   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   4:   xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
   5:   xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
   6:   mc:Ignorable="d"
   7:   Width="500"
   8:   Height="280">
   9:   <Grid x:Name="LayoutRoot"
  10:         Background="wheat"
  11:         Margin="10">
  12:     <Grid.ColumnDefinitions>
  13:       <ColumnDefinition Width="1*" />
  14:       <ColumnDefinition Width="1*" />
  15:     </Grid.ColumnDefinitions>
  16:     <Grid.RowDefinitions>
  17:       <RowDefinition Height="1.5*" />
  18:       <RowDefinition Height="1*" />
  19:       <RowDefinition Height="1*" />
  20:       <RowDefinition Height="*" />
  21:     </Grid.RowDefinitions>
  22:     
  23:     <TextBlock x:Name="Title"
  24:       Margin="0"
  25:       Text="Multi-select List Box"
  26:       Foreground="Red"
  27:       FontFamily="Georgia"
  28:       FontSize="32"
  29:       HorizontalAlignment="Center"
  30:       VerticalAlignment="Center"
  31:       Grid.ColumnSpan="2" />
  32:     
  33:     <ListBox x:Name="msLB"
  34:       Margin="5"
  35:       Grid.Row="1"
  36:       Grid.Column="0"
  37:       SelectionMode="Multiple" />
  38:     
  39:     <Button x:Name="readyButton"
  40:        Margin="5"
  41:        Grid.Row="1"
  42:        Grid.Column="1"
  43:        Width="100"
  44:        Height="35"
  45:        Content="Click when ready" />
  46:     
  47:     <TextBlock x:Name="Message"
  48:         HorizontalAlignment="Left"
  49:         Margin="5"
  50:         Grid.Row="2"
  51:         Grid.Column="0"
  52:         Grid.ColumnSpan="2"
  53:         Foreground="Blue"
  54:         VerticalAlignment="Bottom"
  55:         FontFamily="Georgia"
  56:         FontSize="18" />
  57:     
  58:   </Grid>
  59: </UserControl>

Note the selection mode set on line 37.

We need an event handler for clicking the button, that will find all the selected items and stringify them for the Message TextBlock:

   1: using System.Collections.Generic;
   2: using System.Windows.Controls;
   3:  
   4: namespace MultiSelectLB
   5: {
   6:    public partial class MainPage : UserControl
   7:    {
   8:       private readonly List<string> presidents =
   9:          new List<string> { "Washington", "Lincoln", "FDR", "Kennedy", "Obama" };
  10:       public MainPage()
  11:       {
  12:          InitializeComponent();
  13:          msLB.ItemsSource = presidents;
  14:          readyButton.Click += BClick;
  15:       }
  16:  
  17:       private void BClick(object sender, System.Windows.RoutedEventArgs e)
  18:       {
  19:          var selectedPresidents = msLB.SelectedItems;
  20:          Message.Text = string.Empty;
  21:          foreach (string presidentName in selectedPresidents)
  22:          {
  23:             if (Message.Text.Length > 0)
  24:             {
  25:                Message.Text += ", ";
  26:             }
  27:             Message.Text += presidentName;
  28:          }     // end foreach
  29:       }        // end BClick
  30:    }           // end class
  31: }              // end namespace

 

As an aside, not that using var for the type in line 19 allows the program to remain type safe without the programmer having to find the specific enumerable that the SelectedItems property will return. Sweet.

Here’s a working example:

Previous Element Binding             Next: Merged Resources

What’s New In Silverlight 3 – Element Binding

In Silverlight 3 you can now use one User Interface element as the binding object for another. This can greatly simplify your code. For example, if you wish to display the value of a slider in a text box, there is no need to create a data object to mediate their connection; you can bind the text box directly to the slider:

   1: <Slider x:Name="sUnBound"
   2:     LargeChange="10"
   3:     Maximum="100"
   4:     SmallChange="1"
   5:     Value="50"
   6:     VerticalAlignment="Bottom" />
   7:  
   8:  <TextBlock x:Name="valueFromElement"
   9:   Text="{Binding Value, Mode=OneWay, 
  10:        ElementName=sUnBound}" />

 

Putting this in a new application will create a slider and a TextBlock and will bind the latter to the former and no code-behind is required at all.

Much more on this in the Mini-tutorial on Element Binding.

Previous: Easier Easing    Next Multi-Select List Box

Mini-Tutorial – Element Binding

What It Is

With element binding, it is now possible to bind the value of one object in your UI directly to a second object, without recourse to binding to a data object or handling events.

How You Do It

The canonical example (for me) is binding a TextBlock to the value of a slider. As the slider moves, the TextBlock is updated with the changing value.

SliderAndTextBlock

Two Approaches

Until Silverlight 3, the easiest way to get this to work was to bind both the Slider and the TextBlcok to a data object. When the slider’s value changed, a property in the data object would be modified, and the TextBlock, also bound to that property would be updated (assuming you had implemented the INotifyPropertyChanged interface as discussed here.

This can still be done, but now you can leave out the data object.

The story is told that Einstein’s explanation of how radio works went like this: “you see, telegraph is like a very long cat. You pull his tail in New York and he meows in L.A.  Radio is exactly the same, but without the cat.”

iStock_Cat_With_HeadphonesXSmall

In Silverlight 3 you leave out the cat, er, DataObject and bind the TextBlock’s text value directly to the Slider’s value:

   1: <TextBlock x:Name="myTextBlock"
   2:      Text="{Binding Value, Mode=OneWay, ElementName=mySlder}"/>

 

An Example is Worth A Thousand Words

The best way to see how the new approach works, and how it simplifies your code (and thus makes maintenance much easier) is to build an application that takes both the old and the new approach.

Our quick demo program will create two sliders, each with an associated TextBlock. The first pair will bind through the agency of a data object, and we’ll track the calls to the get and set of the properties of that data object.

The second pair will bind the Text property of the TextBlock directly to the Value property of the slider.

 

Building It

Begin by creating a new Silverlight Application. I’ll call my project ElementBinding.

I find it much easier to set up my form in Expression Blend 3, so I’ll open that to the same project as well, and draw four rows and 3 columns, adding in the two sliders, three TextBlocks and list box as shown here:

 

ElementBindingLayout

 

The Xaml this creates is shown below (collapsed to its bare essentials):

   1: <UserControl x:Class="ElementBinding.MainPage"
   2:     <!-- name spaces here -->
   3:     Width="650"
   4:     Height="300">
   5:  
   6:   <! other cool stuff here to look at later -->
   7:  
   8:     <!-- the grid created firt in Expression Blend
   9:        then tweaked here -->
  10:   <Grid x:Name="LayoutRoot"
  11:         Background="wheat"
  12:         Margin="10">
  13:    
  14:     <!-- columns and rows defined here -->
  15:  
  16:     <TextBlock x:Name="Title"   />
  17:  
  18:     <Slider x:Name="sBoundToObject"/>
  19:  
  20:     <Slider x:Name="sUnBound"/>
  21:  
  22:     <TextBlock x:Name="ValueFromObject"/>
  23:  
  24:     <TextBlock x:Name="valueFromElement" />
  25:  
  26:     <ListBox x:Name="MessagesFromSliders"/>
  27:   </Grid>
  28: </UserControl>

We’re going to examine all of this in depth, but not all at once.

Note that the first TextBlock (ValueFromObject) and its associated Slider (sBoundToObject)  will both be bound to the same data object.  This is the way things were done before Silverlight 3 and you may well have good reason to continue with this model (e.g., the data object will be applying a transformation or other logic that make the shared connection useful.

 

Element Binding

The new element-to-element binding, however, allows you to bind the second TextBlock (ValueFromElement) directly to a property of the Slider (sUnBound), dramatically reducing the amount of code needed to create this connection.

To be clear, if what you are doing is element binding, then this entire project could be stripped down to the creation of the slider and the TextBlock and the binding of the latter to a property of the former, with no helping code behind.

To see that, you can start a second project, name it ElementBindingSimple, and put the following into the MainPage.xaml file,

   1: <UserControl x:Class="ElementBindingSimple.MainPage"
   2:   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
   3:   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   4:   xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
   5:   xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
   6:   mc:Ignorable="d" d:DesignWidth="640" d:DesignHeight="480">
   7:   <Grid x:Name="LayoutRoot">
   8:     <Grid.RowDefinitions>
   9:       <RowDefinition Height="2*" />
  10:       <RowDefinition Height="8*" />
  11:     </Grid.RowDefinitions>
  12:     <Grid.ColumnDefinitions>
  13:       <ColumnDefinition Width="1*" />
  14:       <ColumnDefinition Width="1*" />
  15:     </Grid.ColumnDefinitions>
  16:     <Slider x:Name="sUnBound"
  17:         Margin="5"
  18:         Grid.Row="0"
  19:         Grid.Column="0"
  20:         LargeChange="10"
  21:         Maximum="100"
  22:         SmallChange="1"
  23:         Value="50"
  24:         VerticalAlignment="Bottom" />
  25:     <TextBlock x:Name="valueFromElement"
  26:      Height="35"
  27:      HorizontalAlignment="Left"
  28:      Margin="5,0,0,0"
  29:      VerticalAlignment="Bottom"
  30:      Width="150"
  31:      Grid.Column="1"
  32:      Grid.Row="0"
  33:      FontFamily="Georgia"
  34:      FontSize="14"
  35:      TextWrapping="Wrap"
  36:      Text="{Binding Value, Mode=OneWay, 
  37:           ElementName=sUnBound}" />
  38:   </Grid>
  39: </UserControl>

You don’t even need to open the code-behind, just run it, as you move the slider, the TextBlock will instantly update with the slider’s current value.

Chasing The Magic

To chase down the difference in the two approaches, let’s get the data-object version working. First we need a data object to bind to. The simpler the better:

I’ll create a new class creatively named DataObject and as you would expect, it will implement INotifyPropertyChanged

In a somewhat unusual design, whose benefit will become apparent when we implement the code to tell us which getters and setters are being called, I’m going to pass the Slider into the constructor for the DataObject, and let the DataObject hold a reference to that slider.

Passing a reference to a UI object to a data object is almost never a great idea; we’re giving the data object way way way too much awareness of the UI tier.

Thus I tie my beloved encapsulation to a rock and flay it with a sharp code editor, in service to my greater concern: keeping our eye on how the slider and the data object and the TextBlock communicate.  (Forgive me 3 Amigos, for I know not what I do).

The constructor will stash the reference to the Slider object in a private member variable (see lines 4-9 below).

   1: public class DataObject  : INotifyPropertyChanged
   2: {
   3:    public event PropertyChangedEventHandler PropertyChanged;
   4:    private Slider mySlider;
   5:  
   6:    public DataObject(Slider theSlider)
   7:    {
   8:       mySlider = theSlider;
   9:    }
  10:  
  11:  
  12:    public double SliderValue
  13:    {
  14:       get
  15:       {
  17:          return mySlider.Value;
  18:       }
  19:       set
  20:       {
  21:          if (PropertyChanged != null)
  22:          {
  23:             PropertyChanged(this, new PropertyChangedEventArgs("SliderValue"));
  24:          }     // end if
  25:          mySlider.Value = value;
  26:       }        // end setter
  27:    }           // end property
  28: }           // end class
  29:  

With the appropriate Binding statements in both the the slider and the TextBlock the sequence of events will be that the user will move the slider, the slider will bind back to the instance of DataObject and the TextBlock, also bound to that instance, will be updated.

   1: <Slider x:Name="sBoundToObject"
   2:   Margin="5"
   3:   Grid.Row="1"
   4:   ToolTipService.ToolTip="Bound to an object"
   5:   LargeChange="10"
   6:   Maximum="100"
   7:   SmallChange="1"
   8:   Value="{Binding SliderValue, Mode=TwoWay}"
   9:   VerticalAlignment="Bottom" />
  10:  
  11: <TextBlock x:Name="ValueFromObject"
  12:     HorizontalAlignment="Left"
  13:     Margin="5,0,0,0"
  14:     Grid.Column="1"
  15:     Grid.Row="1"
  16:     Foreground="Blue"
  17:     VerticalAlignment="Bottom"
  18:     FontFamily="Georgia"
  19:     FontSize="14"
  20:     Width="150"
  21:     Height="35"
  22:     Text="{Binding SliderValue, Mode=TwoWay />
  23:  

Creating The Data Context

Both the slider and the TextBlock are bound to a property SliderValue, but not to a particular object that has that property. In the code-behind we solve that by setting the DataContext for the grid to an instance of DataObject (the dataContext is inherited by all the controls in the grid); see lines 7 and 8 below:

   1: public partial class MainPage : UserControl
   2: {
   3:     public MainPage()
   4:     {
   5:         InitializeComponent();
   6:         sBoundToObject.Value = 50;
   7:         DataObject d = new DataObject( sBoundToObject );
   8:         LayoutRoot.DataContext = d;
   9:     }
  10: }

This still won’t tell us much unless we display the calls to the getter and setter.

For that, we’ll use the Listbox and some code to tell the ListBox that getting and setting is happening, and who it is happening to! 

Let’s return to better practices, and accomplish the notification of a get or set by firing an event: MessageReady

   1: public class DataObject : INotifyPropertyChanged
   2: {
   3:    public event PropertyChangedEventHandler PropertyChanged;
   4:    public delegate void MessageReadyHandler(object sender, MessageEventArgs e);
   5:    public event MessageReadyHandler MessageReady;

Note that our event returns void and has the usual two parameters: an instance of type object, and an instance of EventArgs or a class that derives from EventArges, in this case, a class we’ll created called MessageEventArgs.

Since DataObject is the only class that cares about the MessageEventArgs class, it makes good sense to define it as a nested class as shown on line 3 below

   1: public class DataObject : INotifyPropertyChanged
   2: {
   3:    public class MessageEventArgs : EventArgs
   4:    {
   5:       public MessageEventArgs(object src, string msg)
   6:       {
   7:          Source = src; Message = msg;
   8:       }
   9:       public Object Source { get; set; }
  10:       public string Message { get; set; }
  11:    }
  12:  
  13:    public event PropertyChangedEventHandler PropertyChanged;
  14:    public delegate void MessageReadyHandler(object sender, MessageEventArgs e);
  15:    public event MessageReadyHandler MessageReady;

Using The Event To Display A Message

We’re now in a position to raise the MessageReady event whenever we have something for the ListBox to display. We’ll add code to the get and set of all one of our properties, and to be extra clever we’ll factor out the work of seeing if anyone is interested before we raise the event into a helper method.

   1: public partial class MainPage : UserControl
   2: {
   3:     public MainPage()
   4:     {
   5:          // register the handler for the event
   6:         d.MessageReady += ShowMessage;
   7:     }
   8:  
   9:     // the event handler asks the slider to identify itself before reporting the message
  10:     // and all of that is added to the list box
  11:    public void ShowMessage(object sender, DataObject.MessageEventArgs e)
  12:    {
  13:       Slider sldr = sender as Slider;
  14:       if ( sldr != null )
  15:       {
  16:          MessagesFromSliders.Items.Add(sldr.Name + ": " + e.Message);
  17:          MessagesFromSliders.SelectedIndex = MessagesFromSliders.Items.Count - 1;
  18:       }
  19:    }
  20: }

Testing That Sliders Can Send Messages

To test this, I’ll add a tiny bit of code to the DataObject that will take any slider and have it identify itself through this event handler:

public void SayHi(Slider sldr) { MessageReady(sldr, new MessageEventArgs(sldr, "Hi")); } 

 

Pass this helper method any slider and the slider displays its name followed by the word “Hi.”  Back in MainPage.xaml.cs we can call that method to  test that both sliders can display messages to the ListBox.

DataObject b = new DataObject( sBoundToObject );
LayoutRoot.DataContext = b;
b.MessageReady += ShowMessage;
 
// prove it works
b.SayHi(sBoundToObject);
b.SayHi(sUnBound);

 

The result is two lines added to the list box,

SlidersIdentify

Sending A Message On Each Get or Set

We now tell we tell the getter and setter of all (one) of the DataObject’s properties to report when they are invoked,

   1: public double SliderValue
   2: {
   3:    get
   4:    {
   5:       SendMessage("Getting: " + mySlider.Value.ToString("N2"));
   6:       return mySlider.Value;
   7:    }
   8:    set
   9:    {
  10:       if (PropertyChanged != null)
  11:       {
  12:          PropertyChanged(this, new PropertyChangedEventArgs("SliderValue"));
  13:       }     // end if
  14:       SendMessage("Setting: " + SliderValue.ToString("N2"));
  15:       mySlider.Value = value;
  16:    }        // end setter
  17: }           // end property
 
We’re almost home!  All would be well, but we want the TextBlock to format the slider’s value to two decimal places and there is not a way to do that with what we have so far. What we need is to give the Binding object, that mediates between the UI object (the TextBlock) and its data source (DataObject), a converter. The job of the converter will be to take a value and convert it into an appropriately formatted string,
 
   1: public class LongToFormattedString : IValueConverter
   2: {
   3:    public object Convert(
   4:     object value,
   5:     Type targetType,
   6:     object parameter,
   7:     System.Globalization.CultureInfo culture)
   8:    {
   9:       return string.Format(culture, "{0:N2}", value);
  10:    }
  11:  
  12:  
  13:    public object ConvertBack(
  14:      object value,
  15:      Type targetType,
  16:      object parameter,
  17:      System.Globalization.CultureInfo culture)
  18:    {
  19:       return System.Convert.ToDouble(value);
  20:    }
  21: }     // end class
 
 

Finally we must ensure that this DataConverter is used in the Xaml. That requires registering it as a resource at the top of the Xaml file,

   1: <UserControl.Resources>
   2:     <local:LongToFormattedString x:Key="longConverter" />
   3: </UserControl.Resources>

WE can now use that resource to instruct the binding object to call our converter when given a value:

   1: <TextBlock x:Name="ValueFromObject"
   2:     HorizontalAlignment="Left"
   3:     Margin="5,0,0,0"
   4:     Grid.Column="1"
   5:     Grid.Row="1"
   6:     Foreground="Blue"
   7:     VerticalAlignment="Bottom"
   8:     FontFamily="Georgia"
   9:     FontSize="14"
  10:     Width="150"
  11:     Height="35"
  12:     Text="{Binding SliderValue, Mode=TwoWay, 
  13:           Converter={StaticResource longConverter}}" />  
  14:           <!-- adding the converter  -->

That’s it, piece of pie. 

In the live demo, below, the two sliders identify themselves, and then as you move the sliders the top one makes many a call to the bound-to dataObject, but the bottom slider makes none, as it is bound directly to its slider.

 


What’s New In Silverlight 3? Easier Easing

Animated movement often seems much more natural and realistic if the moving object accelerates up to speed or decelerates before stopping. The technique of adding that change in velocity is called Easing. You can imagine that the acceleration to speed, and the deceleration would create a curve when plotted as distance against time, and in fact in prior versions of Expression Blend that curve was often hand drawn as shown in the following two images,

 

easier easing.easing1

Image 1 – Starting to set Easing

 

easier easing.Easing2
Image 2 – Adding In Easing

 

Typically this was presented to the developer as follows “... and then you want to drag this over a bit to add some easing and make things more realistic...”

The typical developer’s reaction was....

 

Easing Scream

perhaps somewhat less than what the designer might have hoped for.

 

In Expression Blend 3 Easing is much more intuitive, starting with a drop down menu that acts as a menu for the most common types of easing used, with each pre-defined and illustrated as shown here:

 

easier easing.Easing4

 

Among the predefined easing formulae are spring and bounce; adding these to your animation can provide tremendously enhanced realism. 

A review of this topic can be found in the mini-tutorial Easing Is Easier and a new video is available as well.

 

 

Previous: Validation   Next Element Binding

Posted by jesseliberty | 8 comment(s)
Filed under: ,

The Great Video Instruction Debate

Over the past year or so I’ve noted that there is a sizable sub-group who feel that our How Do I videos are of marginal or negative value. This was crystallized by a series of emails that I’ll condense in the hope we can begin a discussion.

HDIVideo(This image is live, click to see the video on Data Validation)

The strong version of the argument is this:

Please avoid screencasts, especially if for developers as screen casts won’t be watched, won’t be searchable, don’t allow the user to jump to the important parts.  For some things screencasts are useful (like illustrating a particularly tricky UI task), but for many, they are just lazy. MSDN and particularly Silverlight.net have been producing too many videos.

 

I would open the discussion in response by agreeing that correctness is paramount, and that not all videos are information rich or engaging, but suggested that the audience probably follows something approximating a normal distribution:

VideoBellCurve

In short, we are producing a lot of videos because our download numbers indicate that they are very popular. Given that I occasionally cover the same material in any of three formats

  • Video
  • Mini-Tutorial
  • Full Tutorial

and that videos almost always swamp the others in number of downloads, I think there is empirical evidence that some folks do find them a useful approach.

That said, the raised concerns that they are not searchable or indexable is more than legitimate, and we have creative ideas about fixing or ameliorating that problem that we’ll be talking about soon.

In the interim, I suggested taking a look both at:

Thanks and I look forward to a lively discussion.

Next