2010-05-06 9 views
6

tengo una columna definida como esto:¿Aparece el texto de formato WPF?

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

Pero en lugar de mostrar el tamaño del archivo como un número grande, me gustaría mostrar las unidades, pero todavía tienen que ordenar por el actual FileSizeBytes. ¿Hay alguna forma de ejecutarlo a través de una función o algo así antes de mostrarlo?


@Igor:

funciona muy bien.

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

Respuesta

2

La unión a una función es posible en WPF, pero es generalmente dolorosa. En este caso, un enfoque más elegante sería crear otra propiedad que devuelva una cadena formateada y se una a eso.

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

En XAML, se unen a FileSizeFormatted:

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

EDITAR solución alternativa, gracias a Charlie por señalar esto.

Puede escribir su propio convertidor de valor implementando 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(); 
    } 
} 

Luego, en 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

En el caso de que no pueda agregar otra propiedad a la clase fuente (puede haber una variedad de razones para esto), la otra solución sería crear un IValueConverter y entregarlo al Enlace utilizando la propiedad Convertidor. Luego, cada vez que las actualizaciones de enlace se ejecutarán primero a través del código del convertidor. – Charlie

+0

Sí, buen punto. Una alternativa sería envolver la clase fuente en un modelo de vista, que en algunos casos podría ser una exageración. –

+0

La razón por la que no quiero ir con más propiedades es porque tengo que activar un evento PropertyChanged para cada una de ellas ... ¡Podría terminar con docenas de factores desencadenantes, todo por lo que es esencialmente lo mismo! Además, estás atando la presentación con datos. Aunque me gusta el segundo sol'n. – mpen

1

Para efectos de formato, la aplicación adecuada es la definición de un IValueConverter. Compruebe esta muestra: link text

4

Puede intentar usar StringFormat en su expresión de enlace si está usando .NET 3.5SP1 o posterior. Vea this post on Lester's WPF Blog o this post at Vince Sibal's blog para algunos ejemplos de sintaxis. La adición de StringFormat a los enlaces eliminará la mayoría de las necesidades de Value Converters y mantendrá cómodamente su formato con su marcado en lugar de desactivarlo en otra clase. Ciertamente, es mucho menos tipeo también.

Tal vez algo como esto va a funcionar:

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

No estoy seguro de si al hacer clic en el encabezado para ordenar los elementos clasificará como cadenas o como el tipo de datos subyacente, sin embargo, por lo que dependiendo de lo su expresión de formato parece, puede o no obtener el comportamiento de clasificación deseado.

Cuestiones relacionadas