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

Posted

技术标签:

【中文标题】如何使用样式/模板格式化 wpf 中的小数位数?【英文标题】:How to format number of decimal places in wpf using style/template? 【发布时间】:2013-08-24 01:50:22 【问题描述】:

我正在编写一个 WPF 程序,并试图找出一种方法来通过一些可重复的方法(如样式或模板)来格式化 TextBox 中的数据。我有很多文本框(准确地说是 95 个),每个文本框都绑定到自己的数字数据,每个数字数据都可以定义自己的分辨率。例如,如果数据为 99.123,分辨率为 2,则应显示 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

【问题讨论】:

使用IValueConverter?将实际值和分辨率传递给转换器,让它在自己内部为您进行四舍五入。在不知道这 95 个 TextBox 的确切生成方式的情况下,很难建议 StringFormat 发布当前代码和 XAML。否则都是猜测和无益的猜测。 我在问题中添加了更多信息,希望能更清楚。 【参考方案1】:

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

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

【讨论】:

您好,您的解决方案还可以,但我更喜欢使用关键字 N1(2,3...),因为它可以避免拼写错误,并且至少您可以确定它的显示方式。但确实第二个建议没有显示 0 if value 【参考方案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;
        
    

【讨论】:

一些解释会显着提高您的回答质量。【参考方案3】:

您应该在Binding 上使用StringFormat。您可以使用standard string formats 或custom string formats:

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

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

编辑更新的问题

因此,如果您的ViewModel 定义了精度,我建议您将其作为MultiBinding,并创建您自己的IMultiValueConverter。这在实践中非常烦人,从一个简单的绑定到一个需要扩展为 MultiBinding 的绑定,但如果在编译时不知道精度,这几乎是你能做的。您的 IMultiValueConverter 需要获取值和精度,并输出格式化的字符串。您可以使用String.Format 来执行此操作。

但是,对于ContentControl 之类的东西,您可以使用Style 更轻松地做到这一点:

<Style TargetType="x:Type ContentControl">
    <Setter Property="ContentStringFormat" 
            Value="Binding Resolution, StringFormat=N0" />
</Style>

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

【讨论】:

StringFormat 设置为 #,#.00 的示例无法编译 - 逗号被解释为 Binding 标记扩展中属性的分隔符。 @Gigi,你是对的,但你可以像这样轻松使用它:StringFormat=0:#,#.00。我会更新答案以正常工作。 'StringFormat=N0' 效果很好。对于 2 的精度,我希望显示两位小数,但“10.00”除外,在这种情况下,我希望显示“10”。绑定精度时有没有办法做到这一点?看来我得用转换器了。 我认为没有办法更改使用 .NET 字符串格式显示的小数,因此最好编写一个转换器。 你能解释一下为什么使用两个说明符 0:#,#.00,只使用一个就够了吗?

以上是关于如何使用样式/模板格式化 wpf 中的小数位数?的主要内容,如果未能解决你的问题,请参考以下文章

在iOS中找出货币中的小数位数

Excel 常用数据类型自定义格式特殊值等等

js中如何判断一个8位数是不是为日期

WPF中的网格样式没有模板属性?

c语言如何控制小数位数?

如何设置excel里的数字有小数的显示小数,没有小数的直接不显示小数点?(自适应显示小数位数)