Answered How to format numbers in XAML?

  • Wednesday, April 12, 2006 5:47 PM
     
     

    Is there a way to specify how numeric variables are displayed in XAML (a la String.Format)? I want to set number of decimal places, if there's a thousands separator, etc.

    The only thing I've thought of so far is to format the numeric data as a string and bind the string...not exactly what I'd like to do. At some point, I'm also going to need numeric data entry, but it doesn't look like there's a control for that in WPF yet.

     

All Replies

  • Wednesday, April 12, 2006 7:29 PM
     
     Answered
    Take a look at the documentation on value converters (IValueConverter). Basically you specify a class that defines methods for converting object values (your decimal data) to object values (formatted string data), and back again.
  • Wednesday, April 12, 2006 9:10 PM
     
     

    Ahhh... Yes, I've read about IValueConverter. I just didn't think about it. I was looking for some kind of format template and/or a masked edit control. I suppose that might end up in some vendor's WPF control package.

    Thanks very much for your suggestion

  • Thursday, April 13, 2006 12:55 AM
     
     Answered

    here's a generic formatter class i wrote a while back.  used for integers but you can adapt it.

    public class NumberFormatter : IValueConverter
    {
        public object Convert( object value, Type targetType, object
            parameter, System.Globalization.CultureInfo culture )
        {
            try
            {
                    return System.Convert.ToInt32(value).ToString(parameter as string);
            }
            catch(Exception ex)
            {
            }
            return value;
        }
     
        public object ConvertBack( object value, Type targetType, object parameter,
            System.Globalization.CultureInfo culture )
        {
            return null;
        }
    }
     

    the parameter is any formatting string that you pass to ToString().  in the XAML do the following:

    <Window.Resources>
        <local:NumberFormatter x:Key="myNumberFormatter"/>
    </Window.Resources>
     
    ...
     
    <TextBlock Text="{Binding XPath=/ysroot/ResultSet/@availableResults,Converter={StaticResource myNumberFormatter},ConverterParameter=N0,FallbackValue=0}"/>
     
    <TextBlock Text="{Binding XPath=./FileSize,Converter={StaticResource myNumberFormatter},ConverterParameter='#,##0,.00'}"/>

     

    HTH

  • Thursday, April 13, 2006 4:31 PM
     
     

     Way cool

    Thanks for posting the code. I thought I might have to write a converter for each different number format I wanted.

    I see what FallbackValue is for, but I'm curious about ConverterParameter=N0. What does that do? Is that defined elsewhere in your xaml?

  • Thursday, November 15, 2007 10:35 PM
     
     

    I'm trying to do something very similar. However, I've run into a problem. Namely, the commas in the format string aren't being accepted. The following document says "A comma always represents the separator or delimiter of individual tokens. Therefore a literal comma cannot be passed to a markup extension." I wonder if this changed in more recent builds of .NET? It seems like there should be a way to specify an escape sequence...

     

    http://msdn2.microsoft.com/en-us/library/ms747254.aspx

  • Thursday, November 15, 2007 10:37 PM
     
     

    The other thing that I don't like is that it seems like there should be a way to do the formatting without having to create a full blown IValueConverter. IValueConverter is nice, but, in a lot of cases, you just want to format the output and don't care about converting the values back, so, it seems like overkill to have to define a converter. It seems like there should be a way to specify a lambda expression or delegate to do it.

  • Thursday, November 15, 2007 11:01 PM
     
     

    I got it to work using property element syntax instead of property attribute syntax like the following. Still seems like overkill...

     

    <GridViewColumn Header="Bit Rate">

    <GridViewColumn.DisplayMemberBinding>

    <Binding Path="BitRate" Converter="{StaticResource int64Converter}" ConverterParameter="#,# Kbps"/>

    </GridViewColumn.DisplayMemberBinding>

    </GridViewColumn>

  • Saturday, November 17, 2007 6:59 AM
     
     
    There is actually a way to specify a lambda converter directly in xaml.
  • Saturday, September 13, 2008 6:29 AM
     
     Proposed Answer Has Code
    Check this out: http://blogs.msdn.com/llobo/archive/2008/05/19/wpf-3-5-sp1-feature-stringformat.aspx

    It contains more information about:

    <TextBox Text="{Binding Path=Double, StringFormat=F3}"/>

    <ListBox Background="Beige" ItemStringFormat="F3">
    <GridViewColumn Header="Date" 
    DisplayMemberBinding="{Binding XPath=Date, StringFormat=D}" />

    • Proposed As Answer by SiJei Tuesday, August 16, 2011 7:31 PM
    •  
  • Friday, January 02, 2009 10:39 AM
     
     Proposed Answer Has Code

    Following on the previous post about the StringFormat functionality that was added in .NET 3.5 SP1, here is an (admittedly still slightly convoluted) approach I've been using to display comma-formatted numbers without having to resort to element syntax for the binding.

    First, add a reference to the System namespace to your XAML file, e.g.:


        <Window x:Class="MyExampleWindow"
        xmlns=http://schemas.microsoft.com/winfx/2006/xaml/presentation
        xmlns:x=http://schemas.microsoft.com/winfx/2006/xaml
        xmlns:sys="clr-namespace:System;assembly=mscorlib"
        ...

        >


    Next, add the following formatting string to your window's resources:


        <Window.Resources>

            <!-- Formatting string for comma-separated integer values -->
            <sys:String x:Key="CommaFormat">{0:#,0}</sys:String>
            ...
        </Window.Resources>


    And finally, refer to that string within your binding declaration whenever you want to display a value in comma-separated format:


        <TextBlock Text="{Binding Path=PathToAnInteger,StringFormat={StaticResource CommaFormat}}" HorizontalAlignment="Right"/>


    This still isn't as clean as some of the preceding formatting examples (where you can simply write "StringFormat=f3" or "StringFormat=d" or what have you, and not have to mess around with adding a string to the window resources), but I had to jump through the extra hoops in this case because of the curly braces contained within the format string itself.

    (If there's a simpler way to accomplish this that I'm overlooking, however, I'd definitely love to know what it is....)

    • Proposed As Answer by vtortola Thursday, January 29, 2009 5:58 PM
    •  
  • Monday, August 24, 2009 7:18 PM
     
     

    (If there's a simpler way to accomplish this that I'm overlooking, however, I'd definitely love to know what it is....)

    StringFormat={}{#\,0} is a simpler option.  It's still somewhat convoluted, but not bad :)

    -Ryan
  • Monday, August 24, 2009 7:24 PM
     
     

    Sometimes the "{}{#\,0}" syntax doesn't work for me, but I've discovered you can enclose the StringFormat parameter in single quotes, or you can simply escape the curly brackets as in "StringFormat='\{0:$#,##0\}' ". Not sure why the {} syntax isn't always working for me, but the \ escape fills the job in those instances.