¿Cómo formatear el número de decimales en wpf usando estilo/plantilla?


Estoy escribiendo un programa WPF y estoy tratando de encontrar una manera de formatear los datos en un cuadro de texto a través de algún método repetible como un estilo o plantilla. Tengo muchos cuadros de texto (95 para ser exactos) y cada uno está vinculado a sus propios datos numéricos que pueden tener su propia resolución definida. Por ejemplo, si los datos son 99.123 con una resolución de 2, entonces debería mostrar 99.12. Del mismo modo, un valor de datos de 99 y la resolución 3 deben mostrarse como 99.000 (no 99). ¿Hay una manera de hacer ¿esto?

Editar: Debo aclarar, hay 95 cuadros de texto en la pantalla actual en la que estoy trabajando, pero quiero que cada cuadro de texto en las diversas pantallas de mi programa muestre el número correcto de decimales. Ahora que lo pienso, algunos de estos son cuadros de texto (como la pantalla en la que estoy trabajando ahora) y algunos son DataGrids o ListViews, pero si puedo averiguar cómo hacerlo funcionar para cuadros de texto Estoy seguro de que puedo averiguarlo para los otros controles como bien.

No hay mucho código para compartir en este caso, pero intentaré hacerlo más claro:

Tengo un Modelo de vista que contiene las siguientes propiedades (vb.net):

    Public ReadOnly Property Resolution As Integer
        Get
            Return _signal.DisplayResolution
        End Get
    End Property

    Public ReadOnly Property Value As Single
        Get
            Return Math.Round(_signal.DisplayValue, Resolution)
        End Get
    End Property

Y en el XAML tengo:

<UserControl.Resources>
    <vm:SignalViewModel x:Key="Signal" SignalPath="SomeSignal"/>
</UserControl.Resources>
<TextBox Grid.Column="3" IsEnabled="False" Text="{Binding Path=Value, Source={StaticResource Signal}, Mode=OneWay}" />

EDIT2 (mi solución): Resulta que después de alejarme de la computadora por un tiempo, volví para encontrar una respuesta simple que me estaba mirando a la cara. Formatee los datos en el modelo de vista!

    Public ReadOnly Property Value As String
        Get
            Return (Strings.FormatNumber(Math.Round(_signal.DisplayValue, _signal.DisplayResolution), _signal.DisplayResolution))
        End Get
    End Property
Author: David, 2013-08-21

3 answers

Debe usar el StringFormat en el Binding. Puedes usar formatos de cadena estándar , o formatos de cadena personalizados :

<TextBox Text="{Binding Value, StringFormat=N2}" />
<TextBox Text="{Binding Value, StringFormat={}{0:#,#.00}}" />

Tenga en cuenta que StringFormat solo funciona cuando la propiedad de destino es de tipo string. Si está intentando establecer algo como una propiedad Content (typeof(object)), necesitará usar una propiedad personalizada StringFormatConverter (como aquí ), y pase su cadena de formato como ConverterParameter.

Editar para la pregunta actualizada

Por lo tanto, si su ViewModel define la precisión, yo recomendaría hacer esto como un MultiBinding, y crear su propio IMultiValueConverter. Esto es bastante molesto en la práctica, pasar de un simple enlace a uno que necesita expandirse a MultiBinding, pero si la precisión no se conoce en tiempo de compilación, esto es prácticamente todo lo que puede hacer. Su IMultiValueConverter tendría que tomar el valor, y la precisión, y la salida de la cadena formateada. Usted podría hacer esto usando String.Format.

Sin embargo, para cosas como un ContentControl, puede hacer esto mucho más fácilmente con a Style:

<Style TargetType="{x:Type ContentControl}">
    <Setter Property="ContentStringFormat" 
            Value="{Binding Resolution, StringFormat=N{0}}" />
</Style>

Cualquier control que exponga un ContentStringFormat puede ser usado así. Desafortunadamente, TextBox no tiene nada como eso.

 142
Author: Abe Heidebrecht,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-09-04 18:06:21

La respuesta aceptada no muestra 0 en el lugar entero al dar entrada como 0.299. Se nota .3 en la interfaz de usuario de WPF. Así que mi sugerencia de utilizar el siguiente formato de cadena

<TextBox Text="{Binding Value,  StringFormat={}{0:#,0.0}}" 
 4
Author: Manish Dubey,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-01-04 09:37:23
    void NumericTextBoxInput(object sender, TextCompositionEventArgs e)
    {
        TextBox txt = (TextBox)sender;
        var regex = new Regex(@"^[0-9]*(?:\.[0-9]{0,1})?$");
        string str = txt.Text + e.Text.ToString();
        int cntPrc = 0;
        if (str.Contains('.'))
        {
            string[] tokens = str.Split('.');
            if (tokens.Count() > 0)
            {
                string result = tokens[1];
                char[] prc = result.ToCharArray();
                cntPrc = prc.Count();
            }
        }
        if (regex.IsMatch(e.Text) && !(e.Text == "." && ((TextBox)sender).Text.Contains(e.Text)) && (cntPrc < 3))
        {
            e.Handled = false;
        }
        else
        {
            e.Handled = true;
        }
    }
 -1
Author: Monali Pawar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-06-05 11:55:43