In just about every application I’ve ever developed, there’s at least one multi-line text box that takes free form input from the user. In some applications (such as email, Twitter, log entry, etc.) this might be the primary use case. In other applications it might be a simple “description” box hidden away in a properties dialog.

But in any case, it’s always a challenge to use anything more than plain text for a variety of reasons. First of all, even though WPF, Silverlight, and Windows Forms all have built-in rich text controls, they lack the basic UI elements such as toolbars for formatting. In web applications it’s even worse because there is no native rich text control so you gotta find a component.

Then there is the issue of what to do with the data. Windows Forms produces RTF formatted text. WPF and Silverlight produce XAML. Web browsers produce HTML. But these three formats aren’t easily interchangeable and they all suffer from the fact that they look terrible when circumstances require you to present it as plain text.

There is a solution! It’s called markdown. And it’s something you’ve probably used before if you’ve ever used StackOverflow.

With markdown, you can input and store the content as plain text but render it as rich formatted text. The advantage over markup such as HTML is that the syntax is designed to be very readable as plain text. And since the formatting characters are so intuitive and natural, you don’t need superfluous toolbars or menus to format your content. Since there is no need to strip the formatting when displaying as plain text, you don’t need to worry about how it looks on devices or application screens that don’t support rich text.

Markdown

Of course it’s not HTML so it doesn’t support anything like layout or complicated formatting. It’s simply rich text. But it does support links, headings, lists, and images. You can refer to John Gruber’s markdown page for a more thorough explanation of where and how markdown fits in the context of HTML.

So I’m making more of an effort to support and promote markdown everywhere that I use multi-line text boxes and hopefully you’ll consider it too. I set up a WordPress plugin created by Michel Fortin that allows me to compose my posts in markdown. Now I can write blog posts on my iPad much more easily. Next I’ll be looking for ways to translate markdown to XAML FlowDocuments so that I can use it in WPF and Silverlight applications.

Colin Eberhardt has posted a neat multi-purpose value converter that tries various conventional conversion methods to convert from one type to another. This overcomes a frustrating limitation in WPF/Silverlight data binding where the XAML parser is seemingly more intelligent at converting literal values to target types than values sourced from binding expressions.

Unfortunately, the TypeConverter usage will not work in Silverlight but perhaps using the XamlReader technique there’s something that could be done?

Also, a couple of the readers in the comments had a great suggestion to derive the converter from MarkupExtension to simplify the XAML. I think I’m going to have to go back and do that with all of my converters now.

Silverlight 3 introduced a very useful control called a ChildWindow. This is a "modal" dialog box that can contain whatever content you give it and it floats above the rest of the application inside a Popup control. I say "modal" because unlike ShowDialog in WPF or Windows Forms, showing a ChildWindow via the Show method returns immediately, but it does disable the application’s RootVisual which prevents the user from interacting with the rest of the application while the window is showing.

As cool as this control is, I have always been pretty disappointed in the default behavior and look and feel of the ChildWindow class. For example, the animation as it opens and closes is very unnatural and distracting. The overlay that "dims" the rest of the application successfully indicates the modal nature of the control, but it’s too strong I think. In fact I’m fine with just the normal "grey out" that happens when the RootVisual is disabled.

ChildWindow-Normal

A while back I had created a pretty lame ChildWindow template that kinda sorta looked like a Windows 7 Aero window. It was a half-hearted attempt but it looked a lot better than the above. But then I saw a question on StackOverflow asking about creating an Aero glass style window and I decided to revisit the problem and try to come up with something decent.

The first thing to note when trying to customize the ChildWindow template is that you probably ought to start from scratch. The default template is like an onion of nested grids and borders and panels, none of which have any particular significance to the control other than the border named Chrome. This is what ChildWindow uses to handle dragging. Although as I’ll discuss shortly, I think there’s some bugs there.

ChildWindow-Windows7Aero

My ChildWindow template looks like the one in the above screen shot. I tried very hard to make the template "cooperate" with the style. That is whenever possible, I use values from the style or directly applied to the control instead of hard coding colors, paddings, etc in the template which are hard to tweak.

For example, if you want to create more glass area around the white content area, just increase the Padding of the ChildWindow. Padding, of course, does not have to be uniform. You could give it a larger padding on the bottom to make room for Windows Media Player-style controls.

There’s a couple of caveats though…

  • There is no blur! I originally wanted to blur the elements underneath the "glass" areas but I found this to be a lot more difficult than I thought. A blur effect only applies the blur to its associated element and visual children. Since the stuff I want it to blur is only showing through as a result of opacity, the blur has no effect. I suspect there’s a way to do this using a WritableBitmap but I haven’t gone down that rabbit hole just yet.
  • It doesn’t have any open/close transition animations. I took those out on purpose but now I think a very subtle transition is needed to look more natural than the jarring animation from the default style.
  • It doesn’t currently have any visual states defined on the close button which I took out for the sake of keeping the XAML clean for the example. But you can pretty much drop in the transitions from the default template to get that back.
  • Dragging the ChildWindow appears to be jerky for some reason. I think this is a bug in the way ChildWindow handles dragging because Jeff Wilcox’s customized template has the same problem when one of his readers enabled dragging on his Zune style template.

Finally, there are a number of blog posts out there about how to hack the ChildWindow to be non-modal. Tim Huer has an excellent post about this. I have not tried but I don’t see any reason why my template could not also be applied in conjunction with those methods.

To grab the ResourceDictionary that contains the template, click the Show Source link below.

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
                    xmlns:s="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk">

  <Style x:Key="AeroWindowCloseButton" TargetType="Button">
    <Setter Property="Background">
      <Setter.Value>
        <LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
          <GradientStop Color="#FFEEB3AC" Offset="0.009"/>
          <GradientStop Color="#FFDA8578" Offset="0.402"/>
          <GradientStop Color="#FFC64D38" Offset="0.459"/>
          <GradientStop Color="#FFC84934" Offset="0.598"/>
          <GradientStop Color="#FFD48671" Offset="0.885"/>
          <GradientStop Color="#FFE8BBAE" Offset="0.943"/>
        </LinearGradientBrush>
      </Setter.Value>
    </Setter>
    <Setter Property="BorderBrush" Value="#FF5E5E5E"/>
    <Setter Property="BorderThickness" Value="1"/>
    <Setter Property="Foreground" Value="White"/>
    <Setter Property="Padding" Value="3"/>
    <Setter Property="Width" Value="45"/>
    <Setter Property="Height" Value="20"/>
    <Setter Property="IsTabStop" Value="False"/>
    <Setter Property="Template">
      <Setter.Value>
        <ControlTemplate TargetType="Button">
          <Border
            Background="{TemplateBinding Background}"
            BorderBrush="{TemplateBinding BorderBrush}"
            BorderThickness="{TemplateBinding BorderThickness}"
            CornerRadius="0,0,3,3">
            <Path
              Fill="{TemplateBinding Foreground}"
              Width="11"
              Height="10"
              Stretch="Fill"
              Data="F1 M 6.742,3.852 L 9.110,1.559 L 8.910,0.500 L 6.838,0.500 L 4.902,2.435 L 2.967,0.500 L 0.895,0.500 L 0.694,1.559 L 3.062,3.852 L 0.527,6.351 L 0.689,7.600 L 2.967,7.600 L 4.897,5.575 L 6.854,7.600 L 9.115,7.600 L 9.277,6.351 L 6.742,3.852 Z">
              <Path.Stroke>
                <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                  <GradientStop Color="#FF313131" Offset="1"/>
                  <GradientStop Color="#FF8E9092" Offset="0"/>
                </LinearGradientBrush>
              </Path.Stroke>
            </Path>
          </Border>
        </ControlTemplate>
      </Setter.Value>
    </Setter>
  </Style>
  <Style x:Key="AeroWindow" TargetType="s:ChildWindow">
    <Setter Property="Background" Value="White"/>
    <Setter Property="BorderBrush" Value="#FF5E5E5E"/>
    <Setter Property="BorderThickness" Value="1"/>
    <Setter Property="OverlayBrush" Value="Transparent"/>
    <Setter Property="OverlayOpacity" Value="0"/>
    <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
    <Setter Property="VerticalContentAlignment" Value="Stretch"/>
    <Setter Property="Padding" Value="5"/>
    <Setter Property="IsTabStop" Value="false"/>
    <Setter Property="TabNavigation" Value="Cycle"/>
    <Setter Property="UseLayoutRounding" Value="True"/>
    <Setter Property="Template">
      <Setter.Value>
        <ControlTemplate TargetType="s:ChildWindow">
          <Grid x:Name="Root">

            <!-- OVERLAY BEHIND CHILDWINDOW -->
            <Grid
              x:Name="Overlay"
              Background="{TemplateBinding OverlayBrush}"
              Opacity="{TemplateBinding OverlayOpacity}"
              HorizontalAlignment="Stretch"
              VerticalAlignment="Top"/>

            <!-- WINDOW CONTAINER -->
            <Grid x:Name="ContentRoot" Width="{TemplateBinding Width}" Height="{TemplateBinding Height}">
  
              <!-- GLASS BACKGROUND AND BORDER -->
              <!--
              NOTE: This border should not physically contain the rest of the
              window contents because it has an opacity setting that would
              affect all of its children. Instead, a second border is directly
              above it in the z-order and contains the child elements.
              -->
              <Border
                x:Name="Chrome"
                BorderBrush="{TemplateBinding BorderBrush}"
                BorderThickness="{TemplateBinding BorderThickness}"
                CornerRadius="4"
                Opacity="0.9">
                <Border.Background>
                  <LinearGradientBrush MappingMode="Absolute" StartPoint="0,0" EndPoint="1920,0">
                    <GradientStop Color="#FFADC9E5" Offset="0.010"/>
                    <GradientStop Color="#FFA7C2DC" Offset="0.069"/>
                    <GradientStop Color="#FFB7D2EC" Offset="0.084"/>
                    <GradientStop Color="#FFB7D2EC" Offset="0.146"/>
                    <GradientStop Color="#FFA8C4DE" Offset="0.168"/>
                    <GradientStop Color="#FFB8D3ED" Offset="0.455"/>
                    <GradientStop Color="#FFA6C1DB" Offset="0.518"/>
                    <GradientStop Color="#FFB6D1EB" Offset="0.543"/>
                    <GradientStop Color="#FFA7C2DC" Offset="0.604"/>
                    <GradientStop Color="#FFB7D2EC" Offset="0.618"/>
                    <GradientStop Color="#FFB7D2EC" Offset="0.700"/>
                    <GradientStop Color="#FFABC6E1" Offset="0.722"/>
                    <GradientStop Color="#FFB1CEEA" Offset="0.778"/>
                  </LinearGradientBrush>
                </Border.Background>
              </Border>
  
              <!-- WINDOW CONTENTS -->
              <!-- 
              NOTE: This element will not have a visible border. The Chrome element
              provides the visible border but this element needs to have a matching
              thickness and corner radius so that the contents of the window are
              "pushed in" by the same amount.
              -->
              <Border BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="4">

                <Grid>

                  <Grid.RowDefinitions>
                    <RowDefinition Height="25"/>
                    <RowDefinition/>
                  </Grid.RowDefinitions>
                  <Grid.ColumnDefinitions>
                    <ColumnDefinition/>
                    <ColumnDefinition Width="Auto"/>
                  </Grid.ColumnDefinitions>

                  <ContentControl
                    Content="{TemplateBinding Title}"
                    Foreground="#FF393939"
                    FontWeight="Bold"
                    VerticalAlignment="Center"
                    Margin="6,0,6,0"
                    Grid.Row="0"
                    Grid.Column="0"/>

                  <Button
                    x:Name="CloseButton"
                    Style="{StaticResource AeroWindowCloseButton}"
                    BorderBrush="{TemplateBinding BorderBrush}"
                    BorderThickness="1,0,1,1"
                    VerticalAlignment="Top"
                    Margin="0,0,5,0"
                    Grid.Row="0"
                    Grid.Column="1"/>

                  <Border
                    Background="{TemplateBinding Background}"
                    BorderBrush="{TemplateBinding BorderBrush}"
                    BorderThickness="{TemplateBinding BorderThickness}"
                    Margin="{TemplateBinding Padding}"
                    Grid.Row="1"
                    Grid.ColumnSpan="2">

                    <ContentPresenter
                      x:Name="ContentPresenter"
                      Content="{TemplateBinding Content}"
                      ContentTemplate="{TemplateBinding ContentTemplate}"
                      HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                      VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>

                  </Border>

                </Grid>
              </Border>
            </Grid>
          </Grid>
        </ControlTemplate>
      </Setter.Value>
    </Setter>
  </Style>
</ResourceDictionary>

Download the example project which includes the source for SwitchConverter and SwitchedContent.

I figured I would write some more about value converters since I think there’s a lot of cool things you can do with them, especially when you put a little extra effort into generalizing them.

One thing I find I need to do often is to show content conditionally depending on a certain data binding condition. For example, let’s say we had a WeatherReport object that had a Condition property that had the following enumeration values: Sunny, Cloudy, Rain, Snow. We want to have a different image for each condition.

In WPF you can do this using a DataTrigger but even that is a bit verbose for my tastes. In Silverlight it’s a lot more difficult. The Expression Blend SDK gives you a behavior called a DataTrigger that can achieve this. But I think a value converter would do this job quite well and the markup will be the same for WPF and Silverlight. Check out the following snippet:

<Grid>
    <Grid.Resources>
        <e:SwitchConverter x:Key="WeatherIcons">
            <e:SwitchCase When="Sunny" Then="Sunny.png" />
            <e:SwitchCase When="Cloudy" Then="Cloudy.png" />
            <e:SwitchCase When="Rain" Then="Rain.png" />
            <e:SwitchCase When="Snow" Then="Snow.png" />
        </e:SwitchConverter>
    </Grid.Resources>
    <Image Source="{Binding Condition, Converter={StaticResource WeatherIcons}}" />
</Grid>

SwitchConverterDemo

The only thing that was a little bit tricky about this converter was making sure that the value being bound to could be compared against the strings in the When attribute. At first I naively just figured I could "ToString" the input value to the converter and compare that against the When values. But this is very fragile. For example, if the input were a DateTime, the values "6/25/2010" and "6/25/2010 12:00:00 AM" would not be considered equal. That’s not even considering the fact that regional settings would cause even bigger headaches.

So this implementation simply tries to use the IConvertible interface to normalize the values before comparing them. My actual implementation uses a very complex series of checks that take into account available Parse methods, TypeConverter, etc. But it’s a lot of code that I didn’t want to junk up the example with.

The only other thing worth mentioning is that the SwitchConverter has a ContentProperty attribute that allows us to specify the SwitchCase elements inline, making the resulting XAML pretty clean if you ask me. ContentPropertyAttribute is a little known and underused attribute that lets you specify which property will be set by content in between the element tags. There are a lot of places where this should probably be applied such as DataGrid.Columns, Setter.Value, etc. But now I’m going off on a tangent.

So while this solution is in no way a replacement for a good ViewModel, it does let you cleanly represent conditional content in XAML which really sits well with the OCD part of my brain that hates ugly markup.

As a bonus, I’ve also included a SwitchedContent control that makes it much easier to swap out entire elements based upon the conditional input. An example of that is shown below.

<Button Command="{Binding IncrementCommand}">
    <e:SwitchedContent Binding="{Binding Count}" Else="Overflow!">
        <e:SwitchCase When="0" Then="Zero" />
        <e:SwitchCase When="1" Then="One" />
        <e:SwitchCase When="2" Then="Two" />
        <e:SwitchCase When="3" Then="Three" />
        <e:SwitchCase When="4" Then="Four" />
        <e:SwitchCase When="5" Then="Five" />
        <e:SwitchCase When="6" Then="Six" />
        <e:SwitchCase When="7" Then="Seven" />
        <e:SwitchCase When="8" Then="Eight" />
        <e:SwitchCase When="9" Then="Nine" />
        <e:SwitchCase When="10" Then="Ten" />
    </e:SwitchedContent>
</Button>

Download the example project which includes the source for SwitchConverter and SwitchedContent.

I came across a question on StackOverflow that is a very frequently asked question regarding data binding in XAML. Given a boolean, how do you bind the opposite value to the target? The answer of course is to use a value converter (a class implementing IValueConverter) and invert the boolean in code.

I do this a lot though so I have a NegateConverter in "Josh’s Toolbox". My NegateConverter can negate a lot of things, not just booleans. For example, numeric values, Visibility, Thickness, Point, etc. Now I’ll probably never need to negate a Point but I figured what the hell. The code isn’t very pretty and if you don’t like if statements, just stop reading. It’s utilitarian, get over it.

Can you think of anything else that can be easily negated? (Click Show Source below.)

/// <summary>
/// Produces an output value that is the negative of the input.
/// </summary>
/// <remarks>
/// The built-in signed types are supported as well as a handful of other
/// commonly used types such as <see cref="T:Point"/>, <see cref="T:TimeSpan"/>,
/// <see cref="T:Thickness"/>, etc.
/// </remarks>
public sealed class NegateConverter : IValueConverter
{

    #region Fields

    /// <summary>
    /// The default singleton instance of this converter.
    /// </summary>
    public static readonly NegateConverter Default = new NegateConverter( );

    #endregion

    #region Constructors

    /// <summary>
    /// Initializes a new instance of the <see cref="T:NegateConverter"/> class.
    /// </summary>
    public NegateConverter( )
    {
    }

    #endregion

    #region Methods

    /// <summary>
    /// Converts a value.
    /// </summary>
    /// <param name="value">The value produced by the binding source.</param>
    /// <param name="targetType">The type of the binding target property.</param>
    /// <param name="parameter">The converter parameter to use.</param>
    /// <param name="culture">The culture to use in the converter.</param>
    /// <returns>
    /// A converted value. If the method returns null, the valid null value is used.
    /// </returns>
    public object Convert( object value, Type targetType, object parameter, CultureInfo culture )
    {

        if ( value == null ) {
            return null;
        }

        if ( value is double ) {
            return Negate( (double)value );
        }

        if ( value is int ) {
            return Negate( (int)value );
        }

        if ( value is bool ) {
            return Negate( (bool)value );
        }

        if ( value is long ) {
            return Negate( (long)value );
        }

        if ( value is IConvertible ) {
            return Negate( (IConvertible)value, culture );
        }

        if ( value is TimeSpan ) {
            return Negate( (TimeSpan)value );
        }

        if ( value is Point ) {
            return Negate( (Point)value );
        }

        if ( value is Thickness ) {
            return Negate( (Thickness)value );
        }

        throw new ArgumentException( "Cannot negate " + value.GetType( ) + ".", "value" );

    }

    /// <summary>
    /// Converts a value.
    /// </summary>
    /// <param name="value">The value that is produced by the binding target.</param>
    /// <param name="targetType">The type to convert to.</param>
    /// <param name="parameter">The converter parameter to use.</param>
    /// <param name="culture">The culture to use in the converter.</param>
    /// <returns>
    /// A converted value. If the method returns null, the valid null value is used.
    /// </returns>
    public object ConvertBack( object value, Type targetType, object parameter, CultureInfo culture )
    {
        return Convert(value, targetType, parameter, culture);
    }

    /// <summary>
    /// Negates a <see cref="T:TimeSpan"/> value.
    /// </summary>
    /// <param name="value">The value to negate.</param>
    /// <returns>The negated value.</returns>
    private static TimeSpan Negate( TimeSpan value )
    {
        return value.Negate( );
    }

    /// <summary>
    /// Negates a <see cref="T:Point"/> value.
    /// </summary>
    /// <param name="value">The value to negate.</param>
    /// <returns>The negated value.</returns>
    private static Point Negate( Point value )
    {
        return new Point(
            -value.X,
            -value.Y
        );
    }

    /// <summary>
    /// Negates a <see cref="T:Thickness"/> value.
    /// </summary>
    /// <param name="value">The value to negate.</param>
    /// <returns>The negated value.</returns>
    private static Thickness Negate( Thickness value )
    {
        return new Thickness(
            -value.Left,
            -value.Top,
            -value.Right,
            -value.Bottom
        );
    }

    /// <summary>
    /// Negates a <see cref="T:Boolean"/> value.
    /// </summary>
    /// <param name="value">The value to negate.</param>
    /// <returns>The negated value.</returns>
    private static bool Negate( bool value )
    {
        return !value;
    }

    /// <summary>
    /// Negates a <see cref="T:Int32"/> value.
    /// </summary>
    /// <param name="value">The value to negate.</param>
    /// <returns>The negated value.</returns>
    private static int Negate( int value )
    {
        return -value;
    }

    /// <summary>
    /// Negates a <see cref="T:Int64"/> value.
    /// </summary>
    /// <param name="value">The value to negate.</param>
    /// <returns>The negated value.</returns>
    private static long Negate( long value )
    {
        return -value;
    }

    /// <summary>
    /// Negates a <see cref="T:Double"/> value.
    /// </summary>
    /// <param name="value">The value to negate.</param>
    /// <returns>The negated value.</returns>
    private static double Negate( double value )
    {
        return -value;
    }

    /// <summary>
    /// Negates a <see cref="T:IConvertible"/> value by round tripping through
    /// the System.Decimal type.
    /// </summary>
    /// <param name="value">The value to negate.</param>
    /// <param name="formatProvider">The culture information.</param>
    /// <returns>The negated value as the original input type.</returns>
    private static object Negate( IConvertible value, IFormatProvider formatProvider )
    {

        TypeCode inputType = value.GetTypeCode( );

        decimal input = value.ToDecimal( formatProvider );
        decimal output = Decimal.Negate( input );

        return System.Convert.ChangeType( output, inputType, formatProvider );

    }

    #endregion

}   // class

To celebrate the upcoming finale of LOST, I threw this thing together in Silverlight 4 using Expression Blend 4 and Visual Studio 2010. I also used a trial of Goldwave 5 to work on the sound effects.

I’ve included the source code so you can take a look around. This is an example of a pretty barebones MVVM app without the “M”. Some of the techniques I used were XAML storyboards, a simple state machine, semi-transparent overlays to simulate lighting, MediaElement to play audio files, ViewBox to stretch a portion of the view, TransitioningContentControl, etc. just to name a few.

So go ahead, feel important at work like you’re John Locke saving the world in between staff meetings. Just remember to enter the right numbers (with spaces) and push the “EXECUTE” button every 108 minutes or else…

(Or if you just get bored of waiting, click the clock to advance the timer. You can also right click the application to install it to your start menu.)

I find it very frustrating sometimes to get something to build in Blend. Like many developers, I have a "Me.dll" that contains a lot of commonly used classes, custom controls, etc. As you might expect, this DLL often takes dependencies on other DLL’s that must also then be referenced.

In Blend, this can be a pain in the butt because the Silverlight assemblies are scattered into 3 main locations:

  • %ProgramFiles%\Reference Assemblies\Microsoft\Framework\Silverlight\v4.0
  • %ProgramFiles%\Microsoft SDKs\Silverlight\v4.0\Libraries\Client
  • %ProgramFiles%\Microsoft SDKs\Silverlight\v4.0\Toolkit\Apr10\Bin

It gets to be pretty frustrating pointing blend to these various paths to find System.ServiceModel.dll or something.

You can make this a lot easier without copying all the DLL’s by using symbolic links in Windows Vista/7/2008.

To create the symbolic links, open a PowerShell prompt as an administrator. (Make sure you have PowerShell Community Extensions installed, but who doesn’t?) Then paste or type the following script.

Set-Location C:\Temp\Refs

$SearchArgs = @{
    ErrorAction = 'SilentlyContinue'
    Include = @("System.*.dll", "Microsoft.*.dll")
    Exclude = @("*.resources.dll", "*.design.dll")
    Path = @(
        "$($Env:ProgramFiles)\Reference Assemblies\Microsoft\Framework\Silverlight\v4.0\*"
        "$($Env:ProgramFiles)\Microsoft SDKs\Silverlight\v4.0\Libraries\Client\*"
        "$($Env:ProgramFiles)\Microsoft SDKs\Silverlight\v4.0\Toolkit\Apr10\Bin\*"
        "$($Env:ProgramFiles) (x86)\Reference Assemblies\Microsoft\Framework\Silverlight\v4.0\*"
        "$($Env:ProgramFiles) (x86)\Microsoft SDKs\Silverlight\v4.0\Libraries\Client\*"
        "$($Env:ProgramFiles) (x86)\Microsoft SDKs\Silverlight\v4.0\Toolkit\Apr10\Bin\*"
    )
}

Get-ChildItem @SearchArgs | %{

    $LinkPath = $_.Name
    $TargetPath = $_.FullName
    
    Write-Host "$LinkPath -> $TargetPath"
    New-Symlink -Path:$LinkPath -Target:$TargetPath | Out-Null

}

Download MathEvalConverter.zip

Background

With the name Einstein, people typically assume I’m good at math. I have the utmost respect for the physicists and mathemeticians of our time, prior, and beyond. But to be honest, math is not my strong suit. In fact I have great difficulty simply adding or subtracting numbers without the use of a calculator. This deficiency actually worked to my advantage last month when I was observing the users of an application I had recently dogfed.

The application had several numeric input fields that took in costs, prices, commissions, etc. Like any run of the mill business application, these inputs affected various calculations that updated the UI accordingly. But while observing the users I kept noticing a very peculiar behavior. When they would type into a box for Cost, Price, etc. they would whip out a small desk calculator and add up some numbers before typing them into the box.

As it turns out, the values I took for granted as a pre-calculated input often require various "in-your-head" steps before arriving at what I assumed was a known "input".

"The cost of the product is normally $15 but I knocked it down by $3."

Given my mathematical challenges, I was very sympathetic to this situation. I don’t own a desk calculator but I am very familiar with the Start -> Run -> calc.exe ceremony. If I happen to have a PowerShell window open I’ll use that instead.

Did I miss a key requirement? Should there have been more input fields? Not really because the calculation steps are not necessarily formal aspects of the system. They’re mostly things people might normally do in their head had they not happen to have a calculator in front of them. And the type of calculations they perform vary from case to case.

Then I remembered… I encounter this same situation all the time when working in Excel. But Excel’s primary feature is the fact that you can type a "formula" or expression anywhere you’d put a constant value. Wouldn’t it be great if the text boxes in my application offered the same functionality? Well by the end of this post, they will!

The Plan

The idea is that my input boxes would allow the user to enter a number as usual, but if they entered an expression such as "2+2", committing the value would enter "4" into the field. The expression doesn’t need to be preserved, so the value of the field can still be backed by a simple number. Also, I only need to implement very basic expressions. I’ll stick to addition, subtraction, multiplication, division, grouping, and any combination of the above.

I thought about where I might add this functionality. I could subclass TextBox, but then the cells in a DataGrid would need to be addressed separately. I could probably have done it with a behavior but that didn’t seem appropriate either. In the end I decided to implement an IValueConverter. I was already using one to provide currency formatting in the control.

The end result would look like the working example shown below.

The Math Parser

Because this application was an in-browser Silverlight application, I could avoid having to write my own math parser by taking advantage of the HTML bridge and the Eval() method. In short, I would pass the expression to the JavaScript engine to evaluate as if it were a line of code. Of course, I would need to validate the input first to ensure a malicious user could not take advantage of this fact.

To isolate this shortcut into replacable component, I extracted an IMathEvaluator interface that would be defined as follows.

public interface IMathEvaluator {
    bool TryEvaluate(string expression, out decimal value);
}

This allows me to include my JavaScript hack for the sake of this post while admitting that a less lazy developer could substitute a better implementation. One nice thing about this implementation is that I don’t need to determine if the user entered a number or expression. Even if they entered a simple number like 1, I still treat it as an expression.

The implementation is pretty simple too. It simply checks the input against a Regex to ensure it’s not going to pass some malicious payload to the JavaScript engine then calls Eval() via the Silverlight HTML bridge.

public sealed class JScriptMathEvaluator : IMathEvaluator
{
    public bool TryEvaluate(string expression, out decimal value ) {

        // When there's no text, just return zero
        if ( expression == null || expression.Trim().Length == 0 ) {
            value = 0;
            return true;
        }
        
        // remove currency symbols and commas
        // these are added when we format the number but we want to remove them before
        // parsing the text value because it would invalidate the JavaScript syntax
        var numberFormat = CultureInfo.CurrentCulture.NumberFormat;
        expression = expression.Replace( numberFormat.CurrencySymbol, "" );
        expression = expression.Replace( numberFormat.CurrencyGroupSeparator, "" );
        expression = expression.Replace( numberFormat.NumberGroupSeparator, "" );
        expression = expression.Replace( numberFormat.PercentGroupSeparator, "" );

        // Ensure that a simple expression consisting of only digits,
        // parenthases, and four operators (+, -, *, /) are entered.
        // Never pass non-validated input to JavaScript!
        if (Regex.IsMatch(expression, @"^[0-9\.\+\-\*\/\(\)\s]+$" ) ) {

            try {
                object eval = System.Windows.Browser.HtmlPage.Window.Eval( expression );
                value = Convert.ToDecimal(eval);
                return true;
            }   // try
            catch ( Exception ex ) {
                // trace exception or whatever
                // but let the function return false
            }   // catch

        }   // if

        value = 0;
        return false;

    }
}

The Value Converter

In order to convert the user’s input into a number I’ll need to invoke a conversion process when the value of the TextBox changes. I was already doing this with a FormattingConverter that would apply currency formatting to the number and then parse the text value with NumberStyles.

So let’s just derive a class from FormattingConverter with support for the ConvertBack method. We’ll call it MathEvalConverter.

public sealed class MathEvalConverter : FormattingConverter
{

    public MathEvalConverter( )
    {
        MathEvaluator = new JScriptMathEvaluator( );
    }

    public IMathEvaluator MathEvaluator
    {
        get;
        set;
    }

    protected override object ConvertBack( object value, Type targetType, object parameter, CultureInfo culture )
    {

        // View -> ViewModel

        string expression = System.Convert.ToString( value );

        decimal numberValue;
        if ( MathEvaluator != null && MathEvaluator.TryEvaluate( expression, out numberValue ) ) {
            return numberValue;
        }   // if

        // We couldn't parse the expression.
        // Let silverlight reject it because:
        //   - if we throw an exception, it Silverlight bypasses validation events
        //   - if we return DependencyProperty.UnsetValue, the input will just disappear with no error!
        // By returning the unconverted value back to Silverlight, at least they'll see a conversion error.

        return base.ConvertBack( value, targetType, parameter, culture );

    }

}   // class

The converter doesn’t specifically use the JavaScript implementation. It goes through the IMathEvaluator interface which happens to be implemented by JScriptMathEvaluator.

MathEvalConverter In Action

We can apply the MathEvalConverter to any two-way binding between a numeric property on the binding source and a string property on a control. Since it derives from FormattingConverter, we can supply a format string to pretty format the numbers.

<UserControl>
    <FrameworkElement.Resources>
        <Local:MathEvalConverter x:Key="Eval" Format="C2" />
        <Local:FormattingConverter x:Key="Date" Format="d" />
    </FrameworkElement.Resources>
    <Form:DataForm Header="Expense Report">
        <StackPanel>

            <Form:DataField Label="Reported By">
                <TextBox Text="{Binding Name, Mode=TwoWay}" />
            </Form:DataField>

            <Form:DataField Label="Expense Date">
                <TextBox Text="{Binding Date, Converter={StaticResource Date}, Mode=TwoWay}" />
            </Form:DataField>

            <Form:DataField Label="Meals">
                <TextBox Text="{Binding Meals, Converter={StaticResource Eval}, Mode=TwoWay}" />
            </Form:DataField>

        </StackPanel>
    </Form:DataForm>
</UserControl>

Summary

Enough talk. Download the code, and let me know what you think. I have no idea if anyone finds these posts useful if you don’t post comments!

Download MathEvalConverter.zip

Download Animated Number Project

If you’ve used Turbo Tax, you may have noticed the prominent “Federal Refund” box that’s ever-present at the top of the page while you’re figuring out your taxes. I like this UI concept because when most people are filing their taxes, there’s only one number they actually care about and they care about it every step of the way.

One nice little touch about the display is that whenever you make changes to your return that affect the federal refund, instead of the field just changing immediately, it has a nice incrementing (or decrementing if you’re like me) animation. It is a subtle effect that draws your attention to the field whenever it changes. Try the working example below.

Recently I worked on a line of business application that would benefit from a similar UI. The application is for pricing out sales proposals and takes into account cost of goods, retail price, agent commission, etc. At every step of the way, slight changes to the various inputs affect the bottom line which is the profitability of the deal. So the profitability is always displayed on the screen. When the value changes, I wanted to have this smooth animation between numbers just like Turbo Tax. Turns out it isn’t that hard.

Before we begin

I just want to note that if I just wanted to create a one-off solution, it could probably be done in about 10 lines of code with event handlers. The purpose of this article is to create a control that is effortless to use and re-use. If you want, you can just skip to the sample project and look at the code. It’s really not that complex.

Creating the Control

The idea is very simple. A control that lets you bind a numeric value to it and when that value changes, the displayed number should quickly increment or decrement to the new value instead of changing immediately. The example above shows the finished control in action.

At first I didn’t want to do this as a control. I thought maybe there was some way I could do it at the binding level or with an attached property but that didn’t seem to be possible via any of the extensibility points offered by Silverlight. So I decided to make it a control.

What kind of control should it be? Should it derive from ContentControl? TextBlock? Neither of those seemed appropriate because in order to make it work, I would need a strongly typed Value property. Having a simple Content property based on System.Object would imply that it could accept any type. I didn’t want to go crazy supporting different types. For example, there’s no point in making it able to animate between two DateTime values or TimeSpan. I decided to stick with System.Double as the type of the Value property. Any numeric type would be convertible to/from Double and there’s a built in DoubleAnimation that I could take advantage of.

I settled on creating a new class called AnimatedNumber that derives from Control (not ContentControl.) I added two dependency properties:

public class AnimatedNumber : Control {
    // the actual code defines theese as dependency properties
    public double Value { get; set; }
    private double AnimatedValue { get; set; }
}

The idea here is that the Value property is the bindable public property that would be set to a discrete value such as 0, 100, 200, etc. When this happens we will animate the private AnimatedValue property so that over a short period of time, the AnimatedValue property will quickly change from 0, 1, 2, … 100, … 198, 199, 200.

To do this, I included a PropertyChangedCallback with the ValueProperty registration. This callback is invoked whenever the Value property is changed (either via x.Value = 100 or as a result of a binding expression.) In the callback, we’ll run a Storyboard against the AnimatedValue property that uses a DoubleAnimation to interpolate between the old and new values.

private static void OnValueChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
    var senderControl = (AnimatedNumber)sender;
    senderControl.AnimateValue((double)e.NewValue);
}

private void AnimateValue(double newValue)
{
    var animation = new DoubleAnimation();
    animation.Duration = TimeSpan.FromSeconds(1);
    animation.To = newValue;

    var storyboard = new Storyboard();
    storyboard.Duration = TimeSpan.FromSeconds(1);
    storyboard.Children.Add(animation);

    Storyboard.SetTarget(animation, this);
    Storyboard.SetTargetProperty(animation, new PropertyPath("AnimatedValue"));

    storyboard.Begin();
}

So now we have a control that exposes a Value that when changed, triggers an incremental change to the new value in a corresponding AnimatedValue property. But so far, the control has absolutely no visual representation! We’ve only defined the behavior of the control.

Creating a Default Control Template

To add a default control template, add a folder named “Themes” to the root of the project and create a resource dictionary named Generic.xaml. Add a style with no key and a setter that defines a very basic control template. In fact, the only thing this control has is a ContentPresenter that will present the AnimatedValue property. The entire Generic.xaml is only a few lines long. The control doesn’t need anything more than that because we eventually want to use it wherever we’d place “content” such as in a button or label. Let some other control provide the eye candy.

<ResourceDictionary
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:Local="clr-namespace:AnimatedNumberDemo">
  <Style TargetType="Local:AnimatedNumber">
    <Setter Property="Template">
      <Setter.Value>
        <ControlTemplate TargetType="Local:AnimatedNumber">
          <ContentPresenter x:Name="PART_Content" />
        </ControlTemplate>
      </Setter.Value>
    </Setter>
  </Style>
</ResourceDictionary>

The important thing is that we have a ContentPresenter named (exactly) PART_Content. You’ll see why in a second.

To make Silverlight associate the above template with our control, we need to add a line to the constructor, and while we’re at it, override OnApplyTemplate. This is the best place to grab the template part we expect to find (PART_Content) and bind it to the AnimatedValue property.

// Template part
private ContentPresenter PART_Content;

// Default public constructor
public AnimatedNumber() {
    DefaultStyleKey = typeof(AnimatedNumber);
}

protected override void OnApplyTemplate() {

    base.OnApplyTemplate();

    PART_Content = GetTemplateChild("PART_Content") as ContentPresenter;
    if (PART_Content != null) {
        var binding = new Binding("AnimatedValue");
        binding.Source = this;
        PART_Content.SetBinding(ContentPresenter.ContentProperty, binding);
    }

}

Okay, now in theory it should work but I would advise reading the next section first and looking at the *actual* code I attached as opposed to the select snippets I put inline.

Okay, now it should work…

Really this is all that is needed to make the control functional. But it’s a little crude. The attached sample project is a bit more cleaned up than the inline code so far. There’s also additional functionality.

For one, the code above would use the default Double.ToString() conversion which means as the animation was in progress, you’d probably see a huge ugly number with lots of decimal places, no separators, and no currency symbols. The attached control adds a Format property and uses an included FormattingValueConverter. This way you can specify a format string as an attribute in the XAML to get the nice formatting as seen in the demo at the beginning of the article.

Also, the attached control does not create a new Storyboard everytime the value is animated. A single Storyboard is created in the constructor and is reused for the life of the control. The nice thing about this is that multiple changes to the value will “interrupt” the previous animation. So for example if it’s halfway through animation from 0 to 100 and you change it back to 0, it won’t continue to climb to 100 then drop to 0. It will stop climbing at 50 or whatever, and start dropping.

Finally, the attached control provides a TransitionDuration property that lets you control how long the control will spend transitioning. Right now the time is constant which is a little weird.

Using the code is pretty straightforward. The following is an example of a simple button that is bound to a TotalProfit value of the ViewModel and animates the value when it changes.

<Button Style="{StaticResource GlassButton}">
    <StackPanel>
        <TextBlock Text="Total Profit" />
        <Local:AnimatedNumber Value="{Binding TotalProfit}" Format="C2" />
    </StackPanel>
</Button>

Ideas for Additional Improvements

Some things that I didn’t have time to get to but would be nice:

  • Using an easing function to make the animation more fluid
  • Varying the duration of the animation based on how large or small the change is. For example if you changed 1000 to 1009, it’s kind of silly that the control spends 2 seconds making that transition.
  • Adding support for the Visual State Manager. In particular, it would be nice to have 3 states – Positive, Zero, Negative. This way you could color the value red when negative and green when positive without putting too much burden on the consumer of the control.

Please let me know what you think of this example. It’s my first time posting a lenthy example of a Silverlight control but as time permits I’d like to share more of my recent experiences.

Download Animated Number Project

As you may know, Silverlight 2 did not support the mouse wheel natively. You needed to hook into the HTML bridge and access the mouse wheel events from the DOM, hit test the control that it intersected, then act on the mouse wheel data. Silverlight 3 still does not implement the mouse wheel for scrolling by default, but it does expose a MouseWheel event on UIElement that eliminates the need to hook the events in the DOM.

One caveat though is that the MouseWheel event only fires under Internet Explorer or out-of-browser applications. For other browsers and operating systems, you will still need to use the DOM’s mouse wheel events.

So anyway, I wrapped up the mouse wheel code in a “MouseWheelBehavior” that you can just drop onto any element that contains a ScrollViewer element (multi-line textbox, list box, etc.) and it implements vertical scrolling with no code.

MouseWheelBehavior.cs