views:

188

answers:

3
+1  A: 

Binding to a function is possible in WPF, but it's generally painful. In this case a more elegant approach would be to create another property which returns a formatted string and bind to that.

class FileInfo {
  public int FileSizeBytes {get;set;}
  public int FileSizeFormatted {
   get{
     //Using general number format, will put commas between thousands in most locales.
     return FileSizeBytes.ToString("G");
   }
  }
}

In XAML, bind to FileSizeFormatted:

<DataGridTextColumn Binding="{Binding Path=FileSizeBytes, Mode=OneWay}" Header="Size" IsReadOnly="True" />

EDIT Alternative solution, thanks to Charlie for pointing this out.

You could write your own value converter by implementing IValueConverter.

[ValueConversion(typeof(int), typeof(string))]
public class IntConverter : IValueConverter {
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) {
        //needs more sanity checks to make sure the value is really int
        //and that targetType is string
        return ((int)value).ToString("G");
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) {
        //not implemented for now
        throw new NotImplementedException();
    }
}

Then in XAML:

<UserControl.Resources>
  <src:DateConverter x:Key="intConverter"/>
</UserControl.Resources>
...
<DataGridTextColumn Binding="{Binding Path=FileSizeBytes, Mode=OneWay, Converter={StaticResource intConverter}}" Header="Size" IsReadOnly="True" />
Igor Zevaka
In the case that you cannot add another property to the source class (there may be a variety of reasons for this), the other solution would be to create an IValueConverter and give that to the Binding using the Converter property. Then every time the binding updates it will run through the converter code first.
Charlie
Yes, good point. Alternative to that would be to wrap the source class in a viewmodel, which in some cases could be an overkill.
Igor Zevaka
The reason I don't want to go with more properties is because I have to fire a PropertyChanged event for each one of them... I could wind up with dozens of triggers all for what's essentially the same thing! Plus, you're tying presentation with data. I like the 2nd sol'n though.
Mark
+1  A: 

For formatting purposes, the appropriate implementation is defining an IValueConverter. Check this sample out: link text

Anero
+1  A: 

You can try using StringFormat in your binding expression if you're using .NET 3.5SP1 or later. See this post on Lester's WPF Blog or this post at Vince Sibal's blog for some syntax examples. The addition of StringFormat to bindings will eliminate most needs for Value Converters and conveniently keep your formatting with your markup rather than off in another class somewhere. It's certainly a lot less typing, too.

Maybe something like this will work:

<DataGridTextColumn
  Binding="{Binding Path=FileSizeBytes, Mode=OneWay, StringFormat={0:G} bytes}"
  Header="Size" IsReadOnly="True" />

I'm not sure if clicking on the header to sort the items will sort them as strings or as the underlying data type, though, so depending on what your formatting expression looks like, you may or may not get the desired sorting behavior.

Tim Trout