2010-05-06 98 views
6

我有这样定义的列: WPF格式显示文本?

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

不是显示文件大小作为一个大数目,我想显示的单位,但仍然有它排序实际 FileSizeBytes。有什么方法可以在显示它之前通过函数或其他东西运行它?


@Igor:

的伟大工程。

http://img200.imageshack.us/img200/4717/imageget.jpg

[ValueConversion(typeof(long), typeof(string))] 
class FileSizeConverter : IValueConverter 
{ 

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     string[] units = { "B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB" }; 
     double size = (long)value; 
     int unit = 0; 

     while (size >= 1024) 
     { 
      size /= 1024; 
      ++unit; 
     } 

     return String.Format("{0:0.#} {1}", size, units[unit]); 
    } 

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     throw new NotImplementedException(); 
    } 
} 

回答

2

绑定到一个功能是可以在WPF,但它一般痛苦。在这种情况下,更优雅的方法是创建另一个属性,该属性返回格式化的字符串并绑定到该属性。

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"); 
    } 
    } 
} 

在XAML中,结合FileSizeFormatted

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

EDIT替代的解决方案,由于查理指出了这一点。

您可以通过执行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(); 
    } 
} 

然后在XAML:

<UserControl.Resources> 
    <src:DateConverter x:Key="intConverter"/> 
</UserControl.Resources> 
... 
<DataGridTextColumn Binding="{Binding Path=FileSizeBytes, Mode=OneWay, Converter={StaticResource intConverter}}" Header="Size" IsReadOnly="True" /> 
+1

如果您无法将其他属性添加到源类(可能有多种原因),则另一种解决方案是创建一个IValueConverter并使用Converter属性将其绑定到绑定。然后每次绑定更新时,它都会先通过转换器代码运行。 – Charlie 2010-05-06 23:23:00

+0

是的,好点。另一种方法是将源代码包装在视图模型中,在某些情况下这可能是一种矫枉过正。 – 2010-05-06 23:35:29

+0

我不想更多属性的原因是因为我必须为它们中的每一个触发一个PropertyChanged事件......我可以用几十个触发器完成所有本质上相同的事情!另外,你将演示文稿与数据绑定在一起。我喜欢第二次sol'n。 – mpen 2010-05-07 01:25:03

1

用于格式化,合适的实现是一个定义的IValueConverter。检查此示例: link text

4

如果您使用的是.NET 3.5SP1或更高版本,则可以尝试在绑定表达式中使用StringFormat。有关某些语法示例,请参阅this post on Lester's WPF Blogthis post at Vince Sibal's blog。将StringFormat添加到绑定中将消除对值转换器的大多数需求,并方便地使用标记保持格式化,而不是在某个地方的另一个类中关闭。当然,打字也少得多。

也许这样的事情会工作:

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

我不知道,如果点击标题对项目进行排序将它们分类为字符串或基本数据类型,虽然如此,这取决于什么您的格式化表达式看起来像,您可能会也可能不会获得所需的排序行为。