104 votes

Comment formater le nombre de décimales dans wpf en utilisant un style/un modèle ?

Je suis en train d'écrire un programme WPF et j'essaie de trouver un moyen de formater les données d'une TextBox grâce à une méthode reproductible comme un style ou un modèle. J'ai beaucoup de TextBox (95 pour être exact) et chacun est lié à ses propres données numériques qui peuvent avoir leur propre résolution définie. Par exemple, si la donnée est 99.123 avec une résolution de 2, elle doit afficher 99.12. De même, une valeur de données de 99 et une résolution de 3 devraient être affichées comme 99.000 (et non 99). Existe-t-il un moyen de faire cela ?

Edita: Je dois préciser qu'il y a 95 boîtes de texte sur l'écran sur lequel je travaille actuellement, mais je veux que chaque boîte de texte des différents écrans de mon programme affiche le nombre correct de décimales. Maintenant que j'y pense, certains de ces écrans sont des TextBox (comme l'écran sur lequel je travaille actuellement) et d'autres sont des DataGrids ou des ListViews, mais si je peux trouver comment faire fonctionner les TextBox, je suis sûr que je peux le faire pour les autres contrôles également.

Il n'y a pas beaucoup de code à partager dans ce cas mais je vais essayer de le rendre plus clair :

J'ai un modèle de vue qui contient les propriétés suivantes (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

et dans le XAML j'ai :

<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 (ma solution) : Il se trouve qu'après m'être éloigné de l'ordinateur pendant un certain temps, je suis revenu pour trouver une réponse simple qui me sautait aux yeux. Formatez les données dans le modèle de vue !

    Public ReadOnly Property Value As String
        Get
            Return (Strings.FormatNumber(Math.Round(_signal.DisplayValue, _signal.DisplayResolution), _signal.DisplayResolution))
        End Get
    End Property

224voto

Abe Heidebrecht Points 16417

Vous devez utiliser le StringFormat sur le Binding . Vous pouvez utiliser soit formats de chaîne standard ou formats de chaîne personnalisés :

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

Notez que le StringFormat ne fonctionne que lorsque la propriété cible est de type chaîne. Si vous essayez de définir quelque chose comme un Content propriété ( typeof(object) ), vous devrez utiliser un StringFormatConverter ( comme ici ), et passez votre chaîne de format en tant que ConverterParameter .

Modifier pour mettre à jour la question

Donc, si votre ViewModel définit la précision, je recommanderais de le faire en tant que MultiBinding et de créer votre propre IMultiValueConverter . C'est assez ennuyeux dans la pratique, de passer d'une simple liaison à une liaison qui doit être étendue à une MultiBinding mais si la précision n'est pas connue au moment de la compilation, c'est à peu près tout ce que vous pouvez faire. Votre IMultiValueConverter devrait prendre la valeur et la précision, et sortir la chaîne formatée. Vous pourriez le faire en utilisant String.Format .

Cependant, pour des choses comme un ContentControl vous pouvez le faire bien plus facilement avec une Style :

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

Tout contrôle qui expose un ContentStringFormat peut être utilisé comme suit. Malheureusement, TextBox n'a rien de tel.

9voto

Manish Dubey Points 55

La réponse acceptée n'affiche pas 0 à la place d'un nombre entier lors de la saisie comme 0,299. Elle affiche .3 dans l'interface utilisateur WPF. Je suggère donc d'utiliser le format de chaîne suivant

<TextBox Text="{Binding Value,  StringFormat={}{0:#,0.0}}"

-2voto

Monali Pawar Points 1
    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;
        }
    }

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X