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.

Here’s a quickie. I had an issue where I have a ListBox that will (should) never scroll but I need its item selection capability. It is inside of another ScrollViewer (along with some other controls) and that outer ScrollViewer should be what scrolls. Unfortunately ListBox was eating the MouseWheel events, preventing the outer ScrollViewer from scrolling.

A quick Google search didn’t turn up much. I didn’t want to set IsHitTestVisible=False because like I said, I need the selection ability. I also thought changing the template or subclassing ScrollViewer was a bit drastic.

So instead I came up with the following IgnoreMouseWheelBehavior. Technically it’s not ignoring the MouseWheel, but it is “forwarding” the event back up and out of the ListBox. Check it.

/// <summary>
/// Captures and eats MouseWheel events so that a nested ListBox does not
/// prevent an outer scrollable control from scrolling.
/// </summary>
public sealed class IgnoreMouseWheelBehavior : Behavior<UIElement>
{

  protected override void OnAttached( )
  {
      base.OnAttached( );
      AssociatedObject.PreviewMouseWheel += AssociatedObject_PreviewMouseWheel ;
  }

  protected override void OnDetaching( )
  {
      AssociatedObject.PreviewMouseWheel -= AssociatedObject_PreviewMouseWheel;
      base.OnDetaching( );
  }

  void AssociatedObject_PreviewMouseWheel(object sender, MouseWheelEventArgs e)
  {

      e.Handled = true;

      var e2 = new MouseWheelEventArgs(e.MouseDevice,e.Timestamp,e.Delta);
      e2.RoutedEvent = UIElement.MouseWheelEvent;

      AssociatedObject.RaiseEvent(e2);

  }

}

And here’s how you would use it in XAML.

<ScrollViewer Name="IScroll">
    <ListBox Name="IDont">
        <i:Interaction.Behaviors>
            <local:IgnoreMouseWheelBehavior />
        </i:Interaction.Behaviors>
    </ListBox>
</ScrollViewer>

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.

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

It’s way too hard to get an image next to the text content of a Button, TextBlock, ListBoxItem, TreeViewItem, etc. Coming from a Windows Forms background where many controls had an Image property for displaying a small glyph next to text content, I am constantly frustrated by the verbose XAML required to achieve the same in WPF and Silverlight.

<StackPanel>
    <Button>
        <DockPanel>
            <Image Source="Images/Alert.png" />
            <TextBlock Text="Alerts" />
        </DockPanel>
    </Button>
    <Button>
        <DockPanel>
            <Image Source="Images/Color-Blue.png" />
            <TextBlock Text="Blue Category" />
        </DockPanel>
    </Button>
    <Button>
        <DockPanel>
            <Image Source="Images/Color-Green.png" />
            <TextBlock Text="Green Category" />
        </DockPanel>
    </Button>
    <Button>
        <DockPanel>
            <Image Source="Images/Color-Red.png" />
            <TextBlock Text="Red Category" />
        </DockPanel>
    </Button>
</StackPanel>

Well using a WPF markup extension in XAML we can make the code look a little less clunky. Markup extensions (which derive from System.Windows.MarkupExtension) are instantiated similarly to the way attributes are declared in C#. That is to say, there can be positional and/or named parameters. By overriding the ProvideValue you can use those parameters to construct whatever object structure you want and return it. The XAML parser will use this in place of your markup extension when it finds it.

<StackPanel>
    <Button Content="{e:Content Alerts, Image=Images/Alert.png}" />
    <Button Content="{e:Content Blue Category, Image=Images/Color-Blue.png}" />
    <Button Content="{e:Content Green Category, Image=Images/Color-Green.png}" />
    <Button Content="{e:Content Red Category, Image=Images/Color-Red.png}" />
</StackPanel>

Unfortunately Silverlight does not allow you to create custom markup extensions yet so this same technique cannot be applied to Silverlight where the situation is arguably worse with all the toolkit namespaces and such.

The code for the ContentExtension is very straightforward so I’m just going to add it to the end of the post instead of going through the hassle of uploading a project. Enjoy.

/// <summary>
/// A XAML Markup Extension that allows you to combine simple text content with an image
/// alongside instead of having to manually nest the image and text in a panel.
/// </summary>
public class ContentExtension : MarkupExtension
{

    // constructor with positional parameter
    public ContentExtension( string text )
    {
        Text = text;
    }

    // image must be specified as a named parameter
    public ImageSource Image
    {
        get;
        set;
    }

    public string Text
    {
        get;
        set;
    }

    public override object ProvideValue( IServiceProvider serviceProvider )
    {
        return new DockPanel {
            Children = {
                new Image {
                    Source = Image,
                    Stretch = Stretch.None,
                    VerticalAlignment = VerticalAlignment.Center,
                    HorizontalAlignment = HorizontalAlignment.Center,
                    Margin = new Thickness( 5 )
                },
                new TextBlock {
                    VerticalAlignment = VerticalAlignment.Center,
                    Text = Text
                }
            }
        };
    }

}   // class

Content Markup Extension

These aren’t your typical, obvious tips. Head over to the Visual Studio Blog to learn some WPF performance tips that the team picked up during the development of Visual Studio 2010. Some of the performance issues required changes to WPF that we all will benefit from in .NET 4. Others are clever ways to work around various idiosyncracies of WPF.

Take this for example.

Optimize for Remote Desktop scenarios : Use scrolling hint

Also on the topic of Remote Desktop, one area where we needed additional support from WPF was for scrolling in the text editor. As I mentioned above, when in a remote session, all WPF content is transmitted as a bitmap. When the text editor scrolls by a line, that means that the entire contents of the editor region needs to be retransmitted as a bitmap. This, of course can be expensive – the larger the area of the text view, the larger the bitmap and the slower it will be. Fortunately, WPF 4.0 now knows how to issue a “ScrollWindow” command to the remote desktop session which drastically reduces the amount of information transferred across the wire. Only the scroll operation itself (very short) and the newly-exposed line need to be transmitted. To take advantage of this new operation, you need to use the property VisualScrollableAreaClip. There are some restrictions on where this can be used, so read the documentation carefully.

Download FullScreenDemo Project

So now I’m working on an application that will be used at a trade show in a booth. Customers will come up to the application and type in the area code and exchange of their phone number and the application will tell them whether or not they can move their phone number over to us. Piece of cake. But obviously a battleship gray Windows Forms application will simply not do. I chose WPF for the project because it needs to access an offline database, interact with an external COM server (MapPoint), and run full screen with keyboard input.

That last point is what led me to the code I posted tonight. Running a WPF application in full screen mode is pretty trivial.

  • Set WindowStyle = None
  • Set TopMost = True
  • Set WindowState = Maximized

But coming off a recent Silverlight project, I was a little perturbed about the fact that Silverlight can easily “go full screen” and back whereas in WPF it felt really manual. Plus there were a few other improvements I wanted to make that I could easily wrap up into a reusable behavior. For one, using a full-screen window during debugging is a pain in the ass, even with two monitors. Therefore, I want to be able to toggle full screen mode at runtime.

Here are a few common ways that applications enter and exit full screen mode. This behavior supports them all.

  • Many full-screen apps allow the user to toggle full screen mode by double clicking inside the window.
  • Many full-screen apps allow the user to exit full screen mode by pressing escape.
  • Many full-screen apps implicitly enter full screen mode when the window is maximized.

The only one that was tricky was the last one. Since WPF does not have a “StateChanging” event, what was happening was the Window (with its border and title bar) is maximized before the event is raised. By that time, setting the WindowStyle property to remove the caption and border didn’t affect the maximized size so the maximized window was still showing the taskbar. It took a little trial and error but I settled on using WM_SYSCOMMAND.

Usage of the behavior is simple.

<Window ... >

    <i:Interaction.Behaviors>

        <Einstein:FullScreenBehavior
                FullScreenOnDoubleClick="True"
                FullScreenOnMaximize="True"
                RestoreOnEscape="True" />

    </i:Interaction.Behaviors>

</Window>

The attached demo includes the FullScreenBehavior.cs which has no external dependencies. Enjoy.

Full Screen Demo

I’ve finally gotten around to actually playing with Windows Presentation Foundation in Visual Studio and I’m really blown away by the capabilities. As a GUI guy, I can totally appreciate all the work they’ve put into this framework and I am relieved to see most of the problems with GDI+/Windows Forms being addressed. WPF will definitely mean more impressive looking user interfaces that will make “web 2.0” look like DOS.

But what does this mean exactly for Tablet PC’s? Well, with the recent announcements about Origami devices, the landscape is certainly changing drastically. No longer can a Tablet PC developer assume that his application will run in 1024×768 at 96dpi. Even with the Toshiba M200 and other large screen tablets this is already a problem (although it’s a lot easier to deal with more screen real estate than less).

Resolution-independent applications

The first way you can make your applications deal with different resolutions is to create adaptive layouts. That is, make sure your controls stretch when the window is stretched. In some cases, you can have wrapping UI elements or split containers. This is all possible today in Windows Forms. But it doesn’t solve the issue of high density screens that pack lots of pixels into a small physical area. The problem here is that the same application on 1024×768 at 96dpi looks terribly small on a screen with a much higher physical DPI.

The solution is to stop thinking in terms of pixels and start thinking in terms of real world coordinates like inches. Traditionally, this has been very hard to do in Windows programming. Sure, GDI and GDI+ have scale transformations and alternate coordinate systems, but the underlying Windows subsystem does not have this capability, making it practically useless for controls. In WPF, though, everything is consistent. A virtual coordinate system in WPF works great because you can layout your user interface in a predictable size and then if the resolution (number of pixels) or DPI (pixels per inch) changes, your user interface can scale uniformly and still be usable, with no additional work by you, other than applying the scale. The result is just like if you resize a flash movie.

Consistent visual styles

The other problem with developing Tablet PC applications in Windows Forms is that there is no clear user interface guideline for these kinds of devices. For example, the Origami devices seem to be touch-focused rather than pen-focused. If your application is going to run on these devices, you probably want to make sure your UI elements are suitable for fingertips which are bigger and blunter than a stylus (unless you’re a child, a very thin woman, or a really feminine guy, or a gynecologist, etc…) but what is the right size? What works best?

Why does every new Tablet PC programmer have to research this? And once they do, applying these guidelines consistently across a Windows Forms application is not trivial. But with WPF’s style support, you can “skin” your controls just as easily as you would with CSS on the web. I envision some brilliant WPF-minded people at Microsoft will come up with some great style resources which can just be dropped into your WPF form. They might look similar to the look and feel of the Tablet PC Education Pack which has beautiful, large buttons and attractive gradients. I want more applications to look like that and WPF can make it happen.

Ink is a first-class citizen

This really took me by surprise. But in WPF, ink is just built in. It’s in the same runtime as the rest of the presentation components and all of the UI elements that I have seen expose support for the RealTimeStylus API which provides low-level stylus input capabilities. So it’s easy to tell if you were clicked by a pen/finger or clicked by a mouse.

Also collecting and rendering ink has all of the same presentation capabilities such as the render transformations, animation, 3D, etc. But I suspect this will not be as broadly useful as the other capabilities. But it might make for some really cool visual effects for the TEO controls!

Anyway, bottom line is… If you’re thinking about developing applications that will run on these wide variety of devices, you need to consider Windows Presentation Foundation. It’s available for Windows XP and Windows Vista and is currently in beta.