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


91

我正在编写WPF程序,试图通过某种可重复的方法(例如样式或模板)来找到在TextBox中格式化数据的方法。我有很多TextBox(准确地说是95个),每个TextBox都绑定到自己的数字数据,每个数字数据都可以定义自己的分辨率。例如,如果数据是分辨率为2的99.123,则应显示99.12。同样,数据值99和分辨率3应该显示为99.000(而不是99)。有没有办法做到这一点?

编辑: 我应该澄清一下,我正在处理的当前屏幕上有95个文本框,但是我希望程序中各个屏幕上的每个文本框都显示正确的小数位数。现在,我考虑了一下,其中一些是TextBoxes(例如我现在正在处理的屏幕),一些是DataGrids或ListViews,但是如果我能弄清楚如何使其能够用于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}" />

EDIT2(我的解决方案): 事实证明,离开计算机一段时间后,我回来找到一个简单的答案,令我望而却步。在视图模型中格式化数据!

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

1
使用一个IValueConverter?将实际值和分辨率传递给转换器,让它在您内部进行舍入。如果StringFormat不知道这95到底TextBox是如何生成的,很难提出一个建议。
2013年

发布当前代码和XAML。否则,所有的猜测和无益的猜测。
2013年

我向该问题添加了更多信息,希望可以使其更加清楚。
AXG1010

Answers:


193

您应该在StringFormat上使用Binding。您可以使用标准字符串格式自定义字符串格式

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

请注意,StringFormat仅当target属性为字符串类型时才有效。如果您尝试设置类似Content属性(typeof(object))的内容,则需要使用自定义项StringFormatConverter如此处),并将格式字符串作为传递ConverterParameter

编辑更新的问题

因此,如果您ViewModel定义精度,则建议您将其作为MultiBinding并创建您自己的IMultiValueConverter。从简单的绑定到需要扩展为的绑定实际上在这很烦人MultiBinding,但是如果在编译时不知道精度,则几乎可以做所有事情。您IMultiValueConverter将需要获取值和精度,然后输出格式化的字符串。您可以使用进行此操作String.Format

但是,对于类似的事情ContentControl,您可以使用Style

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

ContentStringFormat可以使用任何公开a的控件。不幸的是,TextBox没有那样的东西。


6
将StringFormat设置为的示例#,#.00无法编译-逗号被解释为Binding标记扩展中属性的定界符。
Gigi 2014年

@Gigi,您是对的,但是您可以像这样轻松地使用它:StringFormat={}{0:#,#.00}。我将更新答案以使其正常工作。
安倍·海德布雷希特

'StringFormat = N {0}'非常有用。对于2的精度,我希望显示两个小数,除了“ 10.00”,在这种情况下,我希望显示“ 10”。绑定精度时,有没有办法做到这一点?似乎我必须使用转换器。
Gordon Slysz '16

我不认为有一种方法可以更改使用.NET字符串格式显示的小数,因此最好编写转换器。
安倍·海德布雷希特

您能解释为什么使用两个说明符0:#,#。00,仅使用其中一个就不够了吗?
杨磊

7

在给出像0.299这样的输入时,可接受的答案不会在整数位置显示0。它在WPF UI中显示.3。所以我建议使用以下字符串格式

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

嗨,您的解决方案还可以,但我想使用关键字N1(2,3 ...),因为它可以避免输入错误,并且至少您可以确定它的显示方式。但是,实际上,第二个建议不会像您提到的那样如果值<0则不显示0。
Kevin VDF

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

9
一些解释将大大提高您的答案的质量。
mrun
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.