Categories: Silverlight Posted by Shawn Oster on 12/11/2008 12:10 PM | Comments

One of the great controls released with the Silverlight Toolkit is the NumericUpDown.  Sure it may seem like just a basic textbox that allows user input with the added glory of a spinner that makes it easy to nudge values up or down with a click, which in and of itself is a great benefit, but there is also some lesser known plumbing that allows users to easily extend this control to provide some great user experiences.

One of my favorite user experiences is the way the UpDowns, or spinners as some call them, work in Microsoft Word when you’re adjusting your margins.  The first great thing is that you see a suffix indicating your current unit of measure.  The second, and cooler, thing is if your default measurement unit is inches and you type 10mm it’ll automatically convert 10 millimeters into inches for you, which I think is brilliant especially considering how often UpDowns are used to represent measurements.

image

Using two handy virtuals in NumericUpDown, FormatValue and ParseValue, the same functionality can be created in Silverlight.  I show you how to get started and leave the monkey work of length conversion to you :)

Step 1: Reference the Silverlight Toolkit

The first step is to download the Silverlight Toolkit if you haven’t already, unzip it, create a new Silverlight Application project (I called mine PageLayout because I was inspired by the Page Layout section in Word)  and add a reference to Microsoft.Windows.Controls.Input. 

Microsoft.Windows.Controls.Input Reference

Step 2: Create The LengthUpDown Class

Do the usual right-click Add Class dance and name it LengthUpDown.cs.  We want to descend LengthUpDown from NumericUpDown so add a using statement referencing the toolkit namespace: Microsoft.Windows.Controls.  At this point you should have:

using Microsoft.Windows.Controls;
namespace PageLayout
{
    public class LengthUpDown : NumericUpDown
    {
    }
}

Step 3: FormatValue & ParseValue

So far everything has been prep, let’s do something interesting.  UpDownBase, the class NumericUpDown base derives from, exposes two useful virtual methods: FormatValue and ParseValue. 

FormatValue is responsible for formatting the actual Value as a string for the user.  It is purely for display purposes so you can format it however you like.  You could return the word “three” for the value 3 or in our case append a suffix representing the current measurement unit, such as “mm”.

ParseValue goes the other direction, it takes the user-entered string and converts it back to a double.  This is where you could for example take the word “three” and convert it to 3 or in our case scan the string to see if there is a unit suffix such as mm, cm, pt or px and do the appropriate conversion before returning the value.

The basic skeleton for our LengthUpDown starts something like this:

using System;
using Microsoft.Windows.Controls;
namespace PageLayout
{
    public class LengthUpDown : NumericUpDown
    {
        /// 
        /// Formats the value for display in the control.
        /// 
        protected override string FormatValue()
        {
            string suffix = DetermineMeasurementSuffix();
            return base.FormatValue() + suffix;
        }
        private string DetermineMeasurementSuffix()
        {
            throw new NotImplementedException();
        }
        /// 
        /// Parses the value the user entered and converts it to the
        /// correct value.
        /// 
        protected override double ParseValue(string text)
        {
            double length = ConvertLength(text);
            return length;
        }
        private double ConvertLength(string text)
        {
            throw new NotImplementedException();
        }
    }
}

Step 4: Length Conversion

In an effort not to introduce too many concepts at once and to keep the code samples short I’ve omitted all the actual conversion logic.  In the next few days I’ll post a fully working version that converts between common units of linear measure.  If you’re bored or ambitious go ahead and implement them, they’re fairly easy for a limited number of measurement units.  Here is a little peak at a fun little fluent-interface conversion class that I created (and that will be included in the upcoming project):

if (suffix != String.Empty)
{
    LengthUnit fromUnit = SuffixToLengthUnit(suffix);
    return new ConvertLength(length).From(fromUnit).To(DefaultLengthUnit);
}

Step 5: Using It

Once you’ve implemented your conversion logic, hopefully in another class to maximize unit testing, then you’ll want to actually use your new control. For my example I created the control directly in the project so it’s easy to get it rocking in the application.

Open the page.xaml and add the project’s namespace to the XAML so you can use your new control and plop down an instance of it, leaving you with:

<UserControl x:Class="PageLayout.Page"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:local="clr-namespace:PageLayout"
    Width="400" Height="300">
    <Grid x:Name="LayoutRoot" Background="White">
        <local:LengthUpDown Value="10" />
    </Grid>
</UserControl>

Run the project and you should see a LengthUpDown looking control in the middle of the page.

Step 6: The Next Step

As I mentioned I’ll be posting a more completely control in the coming days but for now you have everything you need to add custom prefixes and suffixes to numeric values in your UpDown controls.

Categories: Zune Posted by Shawn Oster on 11/24/2008 2:11 AM | Comments

One of my passions is music, especially the discovery of new music.  Back in the day I used to walk into Wax Trax Records in Denver or Albums on the Hill in Boulder and walk out with a stack of CDs that I’d grabbed for no other reason than I liked the album art or the tight-pants wearing clerk behind the counter nodded vaguely in its direction.  Sometimes it worked out; Mentallo & The Fixer, Arctic Monkeys (before they were big, bought only because the word Monkey was in their name), and a few others.  Other times it was a huge waste of money.

That is one reason I love the Zune Pass, I no longer have to waste $30 to $80 a month just to discover if I like an album or not.  I can give it a listen a few times and then I decide if it’s worth my hard earned coin.  Yes, even though I have an all-you-can-eat music subscription I still buy all my music as MP3s in the end.  Oddly enough I’m still saving money compared to my previous random sampling method, because sometimes that tight-pants wearing bloke likes some right proper shite.

Enter the new Zune Pass upgrade, which is that you can still listen to everything in their catalog but you now get 10 tracks free a month.  No DRM, you own them even if you cancel you Zune Pass, they are yours.  This is awesome, it’s like free money and I believe it’s the first of its kind of all the online services.  When you break it down you’re really only paying $5 a month to have full listening access to the entire Zune catalog.

I’m also a member of eMusic (which rocks and makes a nice compliment to Zune, especially now that they’ve added audio books), which has a similar concept of paying a fixed price for a fixed number of tracks per month but they only offer 30-second clips of the songs.  Next are the iTunes/Amazon but again, 30-second previews.  Being able to fully absorb an album as well as own 10 of them free and clear, well, I just saved myself $10 a month.

Categories: Silverlight Posted by Shawn Oster on 11/7/2008 12:35 AM | Comments

A common question in the forums has been how to get dynamic icons in the Silverlight Toolkit TreeView and luckily there are quite a few options.

The Icon

Before you can make the icon dynamic you need a place to put it.  The basic idea is to create a HierarchicalDataTemplate and make room for an image:

<stackpanel.resources>
    <controls:hierarchicaldatatemplate 
        x:key="TaxonomyTemplate" 
        itemssource="{Binding Subclasses}">
        <stackpanel orientation="Horizontal">
            <contentpresenter margin="0 0 4 0" content="???" />
            <textblock text="{Binding Classification}" />
        </stackpanel>
    </controls:hierarchicaldatatemplate>
</stackpanel.resources>
<controls:treeview 
    x:name="MasterTree" 
    itemtemplate="{StaticResource TaxonomyTemplate}" />

I've added a ContentPresenter and the Content is what we're interested in setting dynamically.

Option #1 – The Fixed Template

If you have a rigidly defined hierarchy where you know the exact icon you want at each level you’re in luck, there is already a sample showing how to do just that in the NestedHierarchicalDataTemplate scenario, using three separate HierarchicalDataTemplates, one for each level.  This has the advantage of being easy for your designers to style the icons independent of the code, the obvious downside is it’s a fixed structure.

Option #2 – Binding to a Property

Another option is to add an Icon property to your object and bind the Content directly to it, like this:

<contentpresenter margin="0 0 4 0" content="{Binding Icon}" />

In your descendent classes you can override the Icon property and return the appropriate image for that class.  You can even go further and return different images based on state, such as availability, status, quantity, etc. 

Object model purists may be frothing at the mouth, since I dared put UI information into my objects, and in some scenarios I’d completely agree but what we’re doing here is creating UI model objects, not business model objects.  It’s a common pattern and has the great benefit of making your UI testable from inside unit tests instead of having to rely solely on UI macro recorder/playback frameworks.  I go so far as to recommend that if you’re doing a lot with states like icons, if something checked, multi-selection, color-coding, etc. that you create objects that sit between your business object and the actual UI elements.

Anytime you find yourself trying to get directly at a control to set/check state ask yourself if there is something you could be binding to instead.

Option #3 – The ValueConverter

If you’re binding directly to business objects or really don’t like the idea of adding an Icon property to your objects (you know who you are) then you can take all that logic and roll it up into a value converter.  IValueConverters are these great things that convert between two different types of values (I know, shocking).  A classic example is converting between a boolean and the Visibility enum.  We’re going to apply the same concept but this time convert between a type (our business object) and an icon.

First, we need a ValueConverter, what I’m calling the IconConverter:

public class IconConverter : IValueConverter
{
    public object Convert(
        object value, 
        Type targetType, 
        object parameter, 
        CultureInfo culture)
    {
        if (value is Domain)
        {
            // return icon for Domain
        }
        if (value is Family)
        {
            // return icon for Family
        }
        if (value is Genus)
        {
            // return icon for Genus
        }
        return null;
    }
    public object ConvertBack(
        object value, 
        Type targetType, 
        object parameter, 
        CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

Next, add it as a resource in your application so you can use it in your XAML (you will probably also need to add your project’s namespace to the XAML, that is where “local” comes from in my sample):

<usercontrol.resources>
    <local:iconconverter x:key="IconConverter" />
</usercontrol.resources>

Last, set the binding on the content presenter so it knows to use the converter when trying to determine the icon:

<controls:hierarchicaldatatemplate 
    x:key="TaxonomyTemplate" 
    itemssource="{Binding Subclasses}">
    <stackpanel orientation="Horizontal">
        <contentpresenter 
            margin="0 0 4 0"
            content="{Binding Converter={StaticResource IconConverter}}" />
        <textblock text="{Binding Classification}" />
    </stackpanel>
</controls:hierarchicaldatatemplate>

This technique has the advantage of centralizing everything as well as being usable on any type of object you’re using in your TreeView, whether they all descend from a common base-type or not and if you put it in the application’s resources you can use it throughout your application.  It is also still very testable from a unit test, which is always a plus.

The downside is that the is operator is expensive in terms of performance so if you have a lot of different classes you’re checking against, with a lot of items in the tree you may hit some perf issues.  This can be mitigated by keying off of other data that may be unique to your class-hierarchy.

DataType

The WPF crowd is probably jumping up and down saying, “But wait, wait, what about DataTarget?!”  In WPF one way you’d handle dynamic icons is to create a HierarchialDataTemplate per class you wanted to style and set its DataType property so when that Type appeared in the TreeView it would get its custom style.  It works great and is a tasty way to handle these situations but alas it’s not supported in Silverlight.  Personally I actually prefer option #2 and #3 if all you’re doing is changing icons.

Limitless Options

For every option I’ve proposed here there are probably a dozen others based on your specific needs, business objects and user interface.  If you come up with a great solution or have a situation that you don’t feel is covered here then please either leave a comment or visit us in the forums.

Categories: Silverlight Posted by Shawn Oster on 10/28/2008 9:10 PM | Comments

Ever since joining Microsoft back in August 2008 this blog has been pretty quiet and not just because I’ve been rolling around in the autumn leaves on campus but because of this gem, the Silverlight Toolkit.

At its highest level the Silverlight Toolkit is a collection of great controls and utilities that are continually being improved and polished until they are of the highest and most useful caliber.  You can find all the great details about this release over on my fearless leader’s blog and I highly recommend you check it out because beyond saying what the Silverlight Toolkit contains he also explains how it was built, how it will continue to be built and how it will be released in a very agile, very feedback-centric way.

One thing I want to stress is how important you, the developers, designers and those of uncertain vocation, are to this process.  Saying your feedback is valuable isn’t just lip service; we are watching the Issue Tracker, we are reading and responding in the Silverlight Controls forum, we are reading blog comments, in short we are listening to the people who use these controls day in and day out.

One of the features I love most about the Silverlight Toolkit is its iterative nature: We look at feedback, rub our brain cells together, roll up our sleeves and six to eight weeks later we have new controls that are ready to be previewed by the community or existing ones that have been polished to a high sheen by your feedback and continued testing.

I’m really looking forward to seeing what people do with these controls as well as what feedback is out there.  I’ll see everyone in the forums :)

Listening To Robot Rock/Oh Yeah by Daft Punk on Alive: 2007 (Live) in honor of how hard we all worked on this release.  Worked in fact… like robots.

Categories: Zune Posted by Shawn Oster on 9/22/2008 3:23 PM | Comments

With the release of the new coolness otherwise known as the Zune 3.0 update a few people have let me know that my Mp3tag sources that hook into Marketplace data no longer work.  After a little digging the problem was that the Zune team put everything into a namespace thus breaking all the tags I was searching on.  A little search and replace magic and now we have an updated Marketplace.zip.

Get it while it’s hot!

As an aside I was at the EMP, the Experience Music Project in Seattle which is like a huge museum/learning center centered around all things music and I discovered that the Zune team is actually one of the sponsors.  Very cool

Posted by Shawn Oster on 8/11/2008 3:14 PM | Comments

My first weekend living in Seattle is drawing to a close and as the sun very, very slowly sets I figured I'd give a wee status report.

Right now I'm living in an apartment provided so nicely by Microsoft in an area of downtown Seattle called Belltown in a place The Shelby.  It's a fairly modern, clean, 1 bedroom place with a kitchen and dinning nook that fits two people rather well.  Fully furnished though someone should talk to whomever outfitted this place, we need more towel racks, seriously people.  Towel racks.

The area is pretty much full of hipster kids, upscale restaurants, hidden gems, halfway houses and the fire station.  Lot's of scooters go zipping around the place as well so scooter mania has hit here hard as well.  I can walk five blocks into the heart of downtown, six blocks and I'm in the famous Pike's Market, three blocks to a killer Mediterranean restaurant, eight blocks to the Puget Sound waterfront and most importantly one block to my new favorite watering hole, Two Bells.  From the front door I can see the Space Needle just a few blocks away.

First, the food.  The food here is amazing, we have yet to eat at a bad place in downtown Seattle.  First day lunch was at the Zeitoon Cafe where I had a killer panini, dinner at a great sushi place that had items I've never seen before plus three Japanese business men were dinning which is always a good sign.  Next night was pizza at Serious Pie, a small, quaint upscale pizzeria where everyone sits at shared tables while enjoying entirely unique appetizers and pizzas.  A warning though for my purist friends (Jeremy, I'm looking at you) there is no classic New York or Chicago style pizza on the menu so I'm still on a quest for the best New York slice in Seattle.  Tonight's dinner was at Two Bells, a bar & grill that captured my heart and stomach.  Low-key, no pretension bar & grill with killer hamburgers, Guinness on tap and a great mix of people from tattoo'd lasses to couples in Dockers.  It's only a block away from The Shelby and has a high probability of becoming my favorite local watering hole.  Kevin, Billy, Ben, Sean, this is where we'd meet for a pint after work.  I wish like hell we could.

The weather has been great, only the smallest amount of rain, comfortable temps and sunshine.  In fact the first day here I was missing our nice AC unit back in Colorado.  Even downtown there are trees everywhere and when walking by Bell & 4th (one block over) you can look right down to the Sound, or turn your head a bit and on a clear day make out the mountains.  All in all it's a beautiful city and I can see why so many people love it.  I'll report back tomorrow about the traffic though, I'm sure all these people equals one huge traffic problem of evil. 

In fact I'm surprised there is no cohesive public transportation.  There are a half dozen small networks but nothing like the London Underground or D.C. subway system.  A nice gentleman on the plane who bought be my Jack & Ginger attributed this to all the tree huggers who quite literally can't bare to part with a single tree to make way for unified light rail or subway system.  It's the classic curse of the West, since it was developed so much later than the East more people could afford personal transport and so the need was never as great.  Plus the West wasn't exactly settled by socialites and debutantes so finding a nice communal way for everyone to get around probably wasn't on the top of any of these anti-social explorer's lists.

This is my first time as a true Urbanite, living downtown, walking to the local market (Ralph's), being able to stumble home from the bar (Two Bells), walking to the bus for work (The 545 Express), hitting up the clubs (I hear them at night so I know they're around) and generally enjoying not having to fire up the car or spend money on gas to get to 90% of what I need to.  I'm sure once the constant rain and snow hits I won't be whistling such a merry little tune but I'll let the city court me a little while longer.

It still feels surreal, like I'm on some huge extended vacation and that I'm just staying in a suite at some hotel for awhile but I have a feeling after tomorrow that illusion will come crashing down.  A few days of work I'm sure will bring me right back down to Earth :)

Categories: Silverlight Posted by Shawn Oster on 8/8/2008 12:49 PM | Comments

It's all about the snappy opening line, watch any classic movie from the 40's and you'll realize the importance of the opening line.  If you need some evidence check out 'His Girl Friday', at least the first 20 minutes, for some of what I consider some of the back & forth dialog around.  Of course the classic for lines from the 40's is arguably 'Casablanca' and if you've never seen it you owe it to yourself to watch it with a bottle and some friends, you'll be amazed at how many lines come from just that one movie.

The point, if I must make one, is that I've been trying to figure out a snappy black and white, soft focus opening line that says, "Well kids, seems the Universe has called my bluff and it's time to put my money where my mouth is when it comes to Microsoft."  Starting August 11th, 2008 I'll be an official Microsoft employee working as a program manager on the Silverlight team in Seattle, WA.

I'm not sure exactly what that means except that I hear rumors from my new boss Shawn Burke that it's something to do with controls and being open and agile and designing these fancy little usability bundles of love.  Even though my title says "Program Manager" I have a feeling I'm still going to be very code heavy, since code is and always will be my #1 passion and I'll do everything I can to make sure I'm still slinging lines of code on a daily basis like a monkey flings poo.  They probably won't be the production lines of code but that's OK, I can finally admit that while I think my coding kung fu is deadly I have this odd tendency to drop a project once I figure out the core problem.  After that it's just typing and I get a much bigger thrill out of problem solving than solution implementing.

Oddly enough the whole Silverlight mumbo-jumbo isn't what I want to talk about (though I'm sure I will soon enough), it's the uprooting of my life from Denver, CO to Seattle, WA.  It's leaving a job I worked at for 14 years, where I had a team of friends that were more like brothers that oddly enough gave me free rein to try out any crazy design idea that popped into my head.  It's leaving friends that I could count on for anything from making me iced coffee to helping me tow a clutchless car home from Lusk, Wyoming and everything in between.  A huge family, aye, more a clan, that made every family gathering something to be looked forward to rather than dreaded, with everything from some of the best food you've ever tasted to Irish step-dancing to smoking Blues to ballet to a nephew that's obsessed with any kind of construction equipment, preferably in 'Tear Shit Up' yellow.  To all those still in Denver I love you, dearly and deeply.

I will miss Denver, the people, friends, family, the exploding cultural scene, the moments that can't be captured over XBox Live, and yet I'm also excited to be in Seattle, at Microsoft, trying something new, creating new stories, meeting new people, finding new dive bars, playing host to all my visiting friends and family, bringing whatever it is I am to Microsoft (which is usually only bad singing and a love of strong drink) and generally starting a new chapter in my life.

Today is my first day in Seattle, let the adventure begin!

Posted by Shawn Oster on 7/10/2008 7:48 AM | Comments

As I've been working my way through the Silverlight & XAML landscape inside of Visual Studio I've come to realize how much better tools like TextMate, InType & E are at editing straight text. 

I was reminded of this today when I was trying to create a simple code snippet for XAML.  I whipped up a quick little snippet and went to use it how I always do, by typing the shortcut then pressing TAB.  Well, I tabbed and nothing happened.  OK, something happened, I got a tab, which I didn't expect at all.  It should have expanded my code snippet.  TAB TAB just got me two tabs and while I could get it using the highly awkward Ctrl + K, Ctrl + X that seemed just as much work as actually typing it so I ignored that.

After much searching I discovered that I need to put the angle bracket first and then I could get my tab completion to work.  This about blows my fragile little mind since one of the best uses of snippets is to avoid typing those silly brackets in the first place.  I can almost see how the decision was made to require a bracket but it only makes sense from a engineering stand-point, not a usability one.  It completely ignores the fact that angle brackets are not the easiest things to type quickly.

My solution to all of this is two-fold.  First, once I get to Microsoft I'm going to hunt down the XAML IDE team and second to stop using Visual Studio 2008 for editing XAML.  I've setup a good handful of snippets in InType and discovered something odd yet not all that surprising: I can build a full XAML UI by hand in Intype faster than I can do it in Blend and much faster than using Visual Studio.  Anyone that hand-codes HTML won't be too shocked by this because it's fairly common knowledge that a skilled HTML coder can bust out a page faster in a good text editor than in Dreamweaver.

I really hope the Visual Studio IDE team is looking hard at the new wave of tools like Intype & E, they really are that much more productive.

Categories: Silverlight Posted by Shawn Oster on 6/5/2008 9:38 AM | Comments

I've been putting myself through a crash course on Silverlight\WPF these last few days and here are a few random thoughts.  All of this is after a 60 minute breakneck tour of WPF\Silverlight so I'm more than likely missing a whole bunch of things and probably doing things bass-ackwards but hey, that's why they call it learning.

  • There are three stock layout managers (used for placing controls): Canvas, Stack & Grid.  Where is the CSS-style panel?  If designing web pages has taught us anything it's that the grid quickly gets cumbersome.  Note to self if I get hired at Microsoft: Create a CSSLayoutPanel that uses stock CSS to position the controls.
  • I forgot how painful an experience it is to enter XML in Visual Studio.  I've been spoiled by Intype and E TextEditor where you don't need to enter the opening angle bracket to get code completion.  Also, I must be doing something wrong because entering XML attributes is downright painful in Visual Studio.  This is where I'm stuck:
    • Type "<ColumnDefinition "
    • Type "W", brings up Intellisense
    • Tab to complete, you now have Width=""
    • Type "50"
    • Now what?  How do I get beyond the ending quote without a lot of keyboard gymnastics?  I can press Right Arrow or End but they're not quickly reachable from the home row.  I can just type another quote but instead that'll just add a second ending quote which isn't what we want.  What should really happen is that I should be able to press Tab to tab out of quotes and put the caret one space past the ending quote.  This is how TextMate, Intype and E all handle this and it works wonderfully.
  • There needs to be a nice bundle of XAML specific code-snippets.  The argument that all "real" design work is usually done in something like Blend is crap because even with all the great GUI builders like Delphi, Visual Studio, Dreamweaver, etc. people are still constantly dropping down to the code to get that pixel perfect design so might as well offer up some snippets to make it easier.
  • I'd like to talk to the person that decided that Silverlight's margin property should list margin in "L T R B" order while CSS defines it as "T R B L".  It's not exactly a horrible idea but why pollute the knowledge space needlessly and make people remember two almost identical things?  There are obviously a lot of similarities between XAML and semantic XHTML yet instead of easing the transition by reusing common usage patterns they decided  to make things just a little different.  Annoying.
  • For all my whinging defining UI via a markup-style language is definitely a plus, regardless of the angle bracket tax.
  • I wonder if you could represent XAML or WPF as YAML instead?  Staring at all the XML about breaks my head in two.
  • Printing, is that even a possibility with Silverlight?  How many times have I printed something from a web page with zero control over margins, headers, footers, etc.  Seems some very cool label printing applications could be whipped up in Silverlight as well, CD labels, shipping, etc.
Categories: Zune Posted by Shawn Oster on 5/8/2008 11:02 AM | Comments

Another new Zune client update, another ZuneKeys.  For those that don't know ZuneKeys gives you a few hotkeys to control playing and pausing the Zune software from any application (hence why they're called global hotkeys).  I stole the idea from WinAmp because I'm always needing to pause or skip tracks and it's much easier to do it with a quick Ctrl + Alt + Home rather than opening up the software and finding the pause button.

It's a super-tiny 31k app.  Just unzip and run and it sits in your tray listening for a hotkey.  Uou can play, pause, stop, skip tracks or adjust the volume.  If anyone on the Zune team reads this I'd love to know if there are any official messages I can send to the application for control because right now I'm faking it by sending the same messages those fancy (and bulky) multimedia keyboards send.

Download ZuneKeys for Zune 2.5