如何使用样式/模板格式化 wpf 中的小数位数?

我正在写一个 WPF 程序,我试图找出一种方法,通过一些可重复的方法,如样式或模板格式化数据在一个文本框。我有很多文本框(确切地说是95个) ,每个文本框都绑定到自己的数字数据,每个数字数据都可以定义自己的分辨率。例如,如果数据是99.123,分辨率为2,那么它应该显示99.12。类似地,数据值99和分辨率3应该显示为99.000(而不是99)。有办法吗?

编辑: 我应该澄清一下,我正在处理的当前屏幕上有95个 TextBox,但是我希望程序中各个屏幕上的每个 TextBox 都能显示正确的小数位数。现在我想想,其中一些是 TextBoxes (就像我现在正在处理的屏幕) ,一些是 DataGrids 或 ListView,但是如果我能弄清楚如何让它在 TextBoxes 上工作,我相信我也能弄清楚其他控件的工作原理。

在这种情况下没有太多的代码可以共享,但是我会尝试让它更加清晰:

我有一个视图模型,它包含以下属性(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

在 XAML 中,我有:

<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}" />

编辑2(我的解决方案) : 事实证明,在离开电脑一段时间后,我回来找到了一个简单的答案,这个答案就摆在我面前。格式化视图模型中的数据!

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

You should use the StringFormat on the Binding. You can use either standard string formats, or custom string formats:

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

Note that the StringFormat only works when the target property is of type string. If you are trying to set something like a Content property (typeof(object)), you will need to use a custom StringFormatConverter (like here), and pass your format string as the ConverterParameter.

Edit for updated question

So, if your ViewModel defines the precision, I'd recommend doing this as a MultiBinding, and creating your own IMultiValueConverter. This is pretty annoying in practice, to go from a simple binding to one that needs to be expanded out to a MultiBinding, but if the precision isn't known at compile time, this is pretty much all you can do. Your IMultiValueConverter would need to take the value, and the precision, and output the formatted string. You'd be able to do this using String.Format.

However, for things like a ContentControl, you can much more easily do this with a Style:

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

Any control that exposes a ContentStringFormat can be used like this. Unfortunately, TextBox doesn't have anything like that.

    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;
}
}

The accepted answer does not show 0 in integer place on giving input like 0.299. It shows .3 in WPF UI. So my suggestion to use following string format

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