2013-08-21 2 views
61

Sto scrivendo un programma WPF e sto cercando di capire come formattare i dati in un TextBox attraverso un metodo ripetibile come uno stile o un modello. Ho un sacco di TextBox (95 per essere esatti) e ognuno è legato ai propri dati numerici che possono avere ciascuno la propria risoluzione definita. Ad esempio se i dati sono 99.123 con una risoluzione di 2 allora dovrebbe visualizzare 99.12. Allo stesso modo un valore di 99 e la risoluzione 3 dovrebbero essere visualizzati come 99.000 (non 99). C'è un modo per fare questo?Come formattare il numero di posizioni decimali in wpf usando stile/modello?

Edit: vorrei chiarire, ci sono 95 caselle di testo sulla schermata corrente su cui sto lavorando, ma voglio che ogni TextBox in tutte le varie schermate nel mio programma per visualizzare il numero corretto di cifre decimali. Ora che ci penso, alcuni di questi sono TextBox (come lo schermo su cui sto lavorando ora) e alcuni sono DataGrid o ListViews, ma se riesco a capire come farlo funzionare per i TextBox sono sicuro di poter capire anche per gli altri controlli.

Non c'è molto codice di condividere in questo caso, ma cercherò di renderlo più chiaro:

ho una vista del modello che contiene le seguenti proprietà (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 

e in XAML ho:

<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 (soluzione mio): Si scopre che dopo aver camminato via fr dal computer per un po ', sono tornato per trovare una risposta semplice che mi stava fissando in faccia. Formatta i dati nel modello di vista!

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

utilizzare un 'IValueConverter'? Passa il valore effettivo e la risoluzione al convertitore e lascia che esegua l'arrotondamento per te al suo interno. È difficile suggerire un 'StringFormat' senza sapere come vengono generati esattamente questi' 'TextBox' '95. – Viv

+0

Pubblica il codice corrente e XAML. Altrimenti sono tutte speculazioni e indovinate inutili. –

+0

Ho aggiunto qualche altra informazione alla domanda che dovrebbe, se tutto va bene, renderla più chiara. – AXG1010

risposta

124

È consigliabile utilizzare il StringFormat sul Binding. È possibile utilizzare standard string formats, o custom string formats:

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

Si noti che il StringFormat funziona solo quando la proprietà target è di tipo stringa. Se si sta tentando di impostare qualcosa come una proprietà Content (typeof(object)), sarà necessario utilizzare un numero personalizzato StringFormatConverter (like here) e passare la stringa di formato come ConverterParameter.

Modifica per domanda aggiornato

Quindi, se il vostro ViewModel definisce la precisione, mi consiglia di fare questo come un MultiBinding, e creare il proprio IMultiValueConverter. In pratica, è abbastanza fastidioso passare da un semplice binding a uno che deve essere esteso a un MultiBinding, ma se la precisione non è nota al momento della compilazione, questo è praticamente tutto ciò che si può fare. Il tuo IMultiValueConverter dovrebbe prendere il valore e la precisione e produrre la stringa formattata. Saresti in grado di farlo usando String.Format.

Tuttavia, per le cose come un ContentControl, si può molto più facilmente farlo con un Style:

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

Qualsiasi controllo che espone un ContentStringFormat può essere utilizzato in questo modo. Sfortunatamente, TextBox non ha nulla di simile.

+0

Grazie per le informazioni Abe. – AXG1010

+1

L'esempio con StringFormat impostato su '#, #. 00' non viene compilato - la virgola viene interpretata come delimitatore per gli attributi nell'estensione di markup' Binding'. – Gigi

+0

@Gigi, hai ragione, ma puoi facilmente usarlo in questo modo: 'StringFormat = {} {0: #, #. 00}'. Aggiornerò la risposta per funzionare correttamente –

0
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; 
     } 
    } 
+4

Alcune spiegazioni potrebbero migliorare significativamente la qualità della risposta. – mrun

1

La risposta accettata non mostra 0 in posizione intera su un input come 0.299. Mostra .3 nell'interfaccia utente WPF. Quindi il mio suggerimento di utilizzare il seguente formato stringa

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