Estoy escribiendo un programa WPF y estoy tratando de encontrar una forma de formatear datos en un TextBox a través de algún método repetible como un estilo o plantilla. Tengo muchos TextBoxes (95 para ser exactos) y cada uno está vinculado a sus propios datos numéricos que pueden tener cada uno su propia resolución definida. Por ejemplo, si los datos son 99,123 con una resolución de 2, debería mostrar 99,12. De manera similar, un valor de datos de 99 y una resolución 3 deben mostrarse como 99.000 (no 99). ¿Hay alguna forma de hacer esto?
Editar: Debo aclarar, hay 95 TextBoxes en la pantalla actual en la que estoy trabajando, pero quiero que cada TextBox en las distintas pantallas de mi programa muestre el número correcto de lugares decimales. Ahora que lo pienso, algunos de estos son TextBoxes (como la pantalla en la que estoy trabajando ahora) y algunos son DataGrids o ListViews, pero si puedo averiguar cómo hacer que funcione para TextBoxes, estoy seguro de que puedo entender también para los otros controles.
No hay mucho código para compartir en este caso, pero intentaré aclararlo:
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, regresé 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
fuente
IValueConverter
? Pase el valor real y la resolución al convertidor y déjelo redondear por usted mismo. Es difícil sugerir unStringFormat
sin saber exactamente cómoTextBox
se generan estos 95 .Respuestas:
Debería utilizar
StringFormat
en elBinding
. Puede utilizar 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 cadena. Si está intentando establecer algo como unaContent
propiedad (typeof(object)
), necesitará usar un archivo personalizadoStringFormatConverter
( como aquí ) y pasar su cadena de formato comoConverterParameter
.Editar para pregunta actualizada
Entonces, si tu
ViewModel
define la precisión, te recomiendo hacer esto comoMultiBinding
y crear el tuyo propioIMultiValueConverter
. Esto es bastante molesto en la práctica, pasar de un enlace simple a uno que necesita expandirse a unMultiBinding
, pero si no se conoce la precisión en el momento de la compilación, esto es prácticamente todo lo que puede hacer. DeberíaIMultiValueConverter
tomar el valor y la precisión y generar la cadena formateada. Podrías hacer esto usandoString.Format
.Sin embargo, para cosas como a
ContentControl
, puede hacer esto mucho más fácilmente con aStyle
:<Style TargetType="{x:Type ContentControl}"> <Setter Property="ContentStringFormat" Value="{Binding Resolution, StringFormat=N{0}}" /> </Style>
Cualquier control que exponga un
ContentStringFormat
se puede usar así. Desafortunadamente,TextBox
no tiene nada de eso.fuente
#,#.00
no se compila: la coma se interpreta como un delimitador para los atributos en laBinding
extensión de marcado.StringFormat={}{0:#,#.00}
. Actualizaré la respuesta para que funcione correctamente.La respuesta aceptada no muestra 0 en lugar entero al dar una entrada como 0.299. Muestra .3 en la interfaz de usuario de WPF. Entonces mi sugerencia de usar el siguiente formato de cadena
<TextBox Text="{Binding Value, StringFormat={}{0:#,0.0}}"
fuente
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; } }
fuente