J'écris un programme WPF et j'essaie de trouver un moyen de formater les données dans une zone de texte via une méthode répétable comme un style ou un modèle. J'ai beaucoup de TextBoxes (95 pour être exact) et chacune est liée à ses propres données numériques qui peuvent chacune avoir leur propre résolution définie. Par exemple, si les données sont 99,123 avec une résolution de 2, elles doivent afficher 99,12. De même, une valeur de données de 99 et une résolution de 3 doivent être affichées sous la forme 99 000 (et non 99). Y a-t-il un moyen de faire cela?
Edit: Je devrais clarifier, il y a 95 TextBoxes sur l'écran actuel sur lequel je travaille, mais je veux que chaque TextBox des différents écrans de mon programme affiche le nombre correct de décimales. Maintenant que j'y pense, certains d'entre eux sont des TextBoxes (comme l'écran sur lequel je travaille maintenant) et d'autres sont des DataGrids ou ListViews, mais si je peux comprendre comment le faire fonctionner pour les TextBoxes, je suis sûr que je peux comprendre aussi pour les autres contrôles.
Il n'y a pas beaucoup de code à partager dans ce cas, mais je vais essayer de le clarifier:
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 s'avère qu'après s'être éloigné de l'ordinateur pendant un moment, je suis revenu pour trouver une réponse simple qui me regardait en face. 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
la source
IValueConverter
? Transmettez la valeur réelle et la résolution au convertisseur et laissez-le faire l'arrondi pour vous en lui-même. Il est difficile de suggérer unStringFormat
sans savoir exactement comment ces 95TextBox
sont générés.Réponses:
Vous devez utiliser le
StringFormat
sur leBinding
. Vous pouvez utiliser des formats de chaîne standard ou des formats de chaîne personnalisés :<TextBox Text="{Binding Value, StringFormat=N2}" /> <TextBox Text="{Binding Value, StringFormat={}{0:#,#.00}}" />
Notez que le
StringFormat
fonctionne uniquement lorsque la propriété cible est de type string. Si vous essayez de définir quelque chose comme uneContent
propriété (typeof(object)
), vous devrez utiliser une valeur personnaliséeStringFormatConverter
( comme ici ) et passer votre chaîne de format en tant queConverterParameter
.Modifier pour la question mise à jour
Donc, si vous
ViewModel
définissez la précision, je vous recommande de le faire en tant queMultiBinding
, et de créer le vôtreIMultiValueConverter
. C'est assez ennuyeux en pratique, de passer d'une simple liaison à une qui doit être étendue à uneMultiBinding
, 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. VousIMultiValueConverter
devrez prendre la valeur et la précision et afficher la chaîne formatée. Vous pourrez le faire en utilisantString.Format
.Cependant, pour des choses comme a
ContentControl
, vous pouvez le faire beaucoup plus facilement avec unStyle
:<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 ceci. Malheureusement,TextBox
il n'y a rien de tel.la source
#,#.00
ne compile pas - la virgule est interprétée comme un délimiteur pour les attributs dans l'Binding
extension de balisage.StringFormat={}{0:#,#.00}
. Je mettrai à jour la réponse pour qu'elle fonctionne correctement.La réponse acceptée n'affiche pas 0 à la place d'un entier en donnant une entrée comme 0,299. Il montre .3 dans WPF UI. Donc, ma suggestion d'utiliser le format de chaîne suivant
<TextBox Text="{Binding Value, StringFormat={}{0:#,0.0}}"
la source
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; } }
la source