31 May 2010

JavaScript-style Substring in C#

One thing that really bugs me when writing code is having to use unnecessary extra constructs to avoid exceptions or useless default values emerging. One such situation is trimming a string to a particular length e.g.

string sentence = "The quick brown fox jumps over the lazy dog";
string firstFifty = sentence.Substring(0, 50);

I want the first 50 characters from the sentence but in this example we get an ArgumentOutOfRangeException because there aren’t 50 characters in sentence. Not too helpful and it's an easy mistake to make. To avoid the exception we have to do this:

firstFifty = sentence.Length < 50 ? sentence : sentence.Substring(0, 50);

Yikes! That’s a lot of extra rubbish when all I want is the equivalent of LEFT(sentence, 50) in SQL.

We can easily wrap this up in a "Left" method but chances are we’re going to need a “Right” too so instead we can go down the route JavaScript takes with its "slice" function. JavaScript’s string slice can take one integer argument which, if positive, returns characters from the start of the string and, if negative, returns characters from the end of the string. Adding an overload to allow it to take a padding character is probably sensible too. The end result looks like this:

firstFifty = sentence.Slice(50);
// "The quick brown fox jumps over the lazy dog"
string firstTen = sentence.Slice(10);
// "The quick "

string lastTen = sentence.Slice(-10);
// "e lazy dog"

firstFifty = sentence.Slice(50, '=');
// "The quick brown fox jumps over the lazy dog=============="

string lastFifty = sentence.Slice(-50, '=');
// "==============The quick brown fox jumps over the lazy dog"

A lot more concise and quite useful.

public static class StringExtensions
   /// <summary>
   /// Returns a portion of the String value. If value has Length longer than 
   /// maxLength then it is trimmed otherwise value is simply returned.
   /// </summary>
   /// <returns>
   /// String whose Length will be at most equal to maxLength.
   /// </returns>
   public static string Slice(this string value, int maxLength)
      if (value == null) throw new ArgumentNullException("value");
      int start = 0;
      if (maxLength < 0)
         start = value.Length + maxLength;
         maxLength = Math.Abs(maxLength);
      return value.Length < maxLength ? value : value.Substring(start, maxLength);
   /// <summary>
   /// Returns a portion of the String value. If value has Length longer than 
   /// length then it is trimmed otherwise value is padded to length with 
   /// shortfallPaddingChar.
   /// </summary>
   /// <returns>
   /// String whose Length will be equal to length.
   /// </returns>
   public static string Slice(this string value, int length, char shortfallPaddingChar)
      if (value == null) throw new ArgumentNullException("value");
      string part = value.Slice(length);
      int abslen = Math.Abs(length);
      if(abslen > part.Length)
         part = length < 0 ? part.PadLeft(abslen, shortfallPaddingChar) : part.PadRight(abslen, shortfallPaddingChar);
      return part;

25 May 2010

Silverlight 3 Behavior causing XAML error

A recent XAML error I received from a Silverlight Behavior had me going round in circles trying to find the cause for quite a while. I was getting an AG_E_PARSER_BAD_PROPERTY_VALUE in code similar to the following:

<canvas x:name="Blah">
      <myapp:SpecialBehavior Source="{Binding SomeProperty}" />

The error identified the myapp:SpecialBehavior line as the culprit but didn't give me any further information so I proceeded to try and debug the binding to see what was going wrong. This didn’t shed any light on the cause, the binding was being created fine – the error was occurring later on.

This had me stumped for a couple of hours – I even tried setting up Framework source stepping only to find that the Silverlight 3 symbols weren’t yet available. In the end I stumbled upon the answer by chance – looking at the Canvas class in Reflector I noticed that it didn’t inherit from Control, only FrameworkElement via Panel. A quick check of my Behavior code and I found this:

public class SpecialBehavior : Behavior<Control>

It was the Behavior itself that was invalid in the Interaction.Behaviors property due to the incompatible type parameter. I changed Control to FrameworkElement and everything started working fine.

16 May 2010

Running UI operations sequentially in Silverlight

I've been playing around with Silverlight recently and have come across a requirement of needing to wait for the UI to do something before continuing. For example I have a UI with elements such and an image and text bound to properties of a model object. When the model object changes the interface updates to reflect this change but I need to perform an "unload" transition just before the model changes and a "load" transition just after it had changes.

Instead of this:

before I want this:


The orange arrows representing the transitions.

I considered having BeforeChange and AfterChange events, hooking my transition storyboards up to them and then firing them in the model setter. The trouble with this is that the storyboards will be playing in a separate thread so as soon as the BeforeChange one starts our code will have moved on and fired the AfterChange one. The result will be that we'll never see the "before" transition which will ruin the whole effect.

Mike Taulty posted about this same issue in 2008 highlighting that, to achieve the correct result, we end up needing to chain our code together using the Completed events of our storyboards. His solution was using some classes to wrap this up and I've taken a similar approach apart from that I have the sequence defined fluently and included the option of using visual states rather than explicitly defined storyboards.

private Album CurrentAlbum
      return this.DataContext as Album;
      if (CurrentAlbum != value)
         new Sequence()
            .GoTo(this, LayoutRoot, "VisualStateGroup", "AlbumUnloaded")
            .Execute(() =>
               this.DataContext = value;
            .GoTo(this, LayoutRoot, "VisualStateGroup", "AlbumLoaded")

It ends up being a lot quicker to write the code and I think it's quite obvious by reading it what will happen. If the visual state group or states aren't defined then only the inner assignment occurs.

The source for the Sequence class is a bit big for this post so the gist is here: Sequence.cs 


Deferred execution
The storyboard or visual state change Completed event we're waiting for may never happen - do we try to execute the next steps anyway? I’ve taken the approach of firing off the next step in the destructor of the class however it may make more sense to set some arbitrary timeout so if the transition hasn’t completed after say 10 seconds we fire off the next step anyway.
Should we allow a sequence to be created once and then reused many times - we could have an overload of Run() that takes a context object and passes it on to each of the steps. Could run into issues with people using closures like I do in the example. I’ve stuck with single use in the class, throwing an exception if Run() is called a second time.