Hi

 

When working with WPF I always found myself thinking how to handle Data formatting when a WPF control was bound to it. Let’s look at the following example of a window with a TextBlock that displays a DateTime:

   1: <Window x:Class="BindingFormat.Window1"

   2:     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

   3:     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

   4:     Title="Window1" Height="300" Width="300">

   5:     <Grid>

   6:         <TextBlock Text="{Binding}"></TextBlock>

   7:     </Grid>

   8: </Window>

And the code behind:

   1: public Window1()

   2: {

   3:     InitializeComponent();

   4:     DateTime d = DateTime.Now;

   5:     this.DataContext = d;

   6: }

Very Simple.

 

The outcome is this:

 

Binding no Format

But what if we wanted to change the format of the DateTime? Before .NET 3.5 SP1 we had 2 options:

 

Adding a Property

That was the easiest and fastest way to make the data in the UI formatted in the way you wanted let’s say we wanted the DateTime to display like this: 11:49 2/5/2009, we would have done this:

   1: public Window1()

   2: {

   3:     InitializeComponent();

   4:     this.DataContext = this;

   5: }

   6: 

   7: public string Now

   8: {

   9:     get

  10:     {

  11:         return DateTime.Now.ToString("HH:MM d/M/yyyy");

  12:     }

  13: }

and have the UI bind to the Now property:

   1: <Window x:Class="BindingFormat.Window1"

   2:     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

   3:     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

   4:     Title="Window1" Height="300" Width="300">

   5:     <Grid>

   6:         <TextBlock Text="{Binding Now}"></TextBlock>

   7:     </Grid>

   8: </Window>

The outcome is what we wanted:

Using Property to format

I don’t like this way of work for 2 reasons:

  1. It ads clutter to the code behind and mixes data and UI elements because the Now property is strictly UI but it resides in the Data of the application.
  2. There is no way to reuse it, we would have to duplicate the property anywhere we need to display this particular format.

Using a ValueConverter

This is a much better way of work because it solves the 2 problems I had with the Property method of formatting data. Using a converter keeps UI logic in the UI, removes the clutter from the code behind and is reusable.

 

Here is how we do it:

 

First we add the converter:

   1: public class DateTimeConverter : IValueConverter

   2: {

   3:     #region IValueConverter Members

   4: 

   5:     public object Convert(object value, Type targetType, object parameter

   6:                         , System.Globalization.CultureInfo culture)

   7:     {

   8:         if (value is DateTime)

   9:         {

  10:             DateTime d = (DateTime)value;

  11:             return d.ToString("HH:MM d/M/yyyy");

  12:         }

  13:         return string.Empty;

  14:     }

  15: 

  16:     public object ConvertBack(object value, Type targetType, object parameter

  17:                             , System.Globalization.CultureInfo culture)

  18:     {

  19:         throw new NotImplementedException();

  20:     }

  21: 

  22:     #endregion

  23: }

Use it with the binding:

   1: <Window x:Class="BindingFormat.Window1"

   2:     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

   3:     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

   4:         xmlns:local="clr-namespace:BindingFormat"

   5:     Title="Window1" Height="300" Width="300">

   6:     <Window.Resources>

   7:         <local:DateTimeConverter x:Key="BindingCVR"/>

   8:     </Window.Resources>

   9:     <Grid>

  10:         <TextBlock Text="{Binding Converter={StaticResource BindingCVR}}"/>

  11:     </Grid>

  12: </Window>

And have the DataContext be DateTime.Now:

   1: public Window1()

   2: {

   3:    InitializeComponent();

   4:    DateTime d = DateTime.Now;

   5:    this.DataContext = d;

   6: }

And the outcome? Just as before:

Using Property to format

The only drawback to this method is that it is takes more effort.

 

But we just got lucky..

 

Using Binding.StringFormat

In .NET 3.5 SP1 we got the StringFormat option in Binding!

 

This makes things so much easier All we have to do is have the Binding Expression look like this:

   1: <TextBlock Text="{Binding StringFormat='HH:MM d/M/yyyy'}"/>

And that’s it, no extra Properties and ValueConverters.

 

I could have copied the image again but trust me it gives the same outcome in a much more elegant way.

 

Do you have a different way of work? let me know.

 

Enjoy

 

Amit

Tags :

6 Responses to “Formatting Your WPF Data – String.Format Is In the House!”


  1. Jmix90

    Said on May 29, 2009 :

    In fact, this makes 3 options and not 2 :-D !

  2. Amit

    Said on May 29, 2009 :

    Indeed it does :)

  3. Andres

    Said on June 23, 2009 :

    Is this blog dead? Where are the updates?

  4. Amit

    Said on July 12, 2009 :

    No not dead :)

    I got married and went on my honeymoon.

    Will be back online shortly!

  5. Pallavi

    Said on December 23, 2009 :

    Hi
    I want to display in Combobox in format “Code – Description”, Code is value member of WPF Combobox. Code & Description are members of class ClassA. I got solution as below:

1 Trackback(s)

  1. Sep 6, 2009: WPF: 90+ Miejsc które warto zna? « Dawid Po?li?ski

Post a Comment