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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18361689/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 23:54:43  来源:igfitidea点击:

How to format number of decimal places in wpf using style/template?

wpfxamldata-bindingstring-formatting

提问by AXG1010

I am writing a WPF program and I am trying to figure out a way to format data in a TextBox through some repeatable method like a style or template. I have a lot of TextBoxes (95 to be exact) and each one is bound to its own numeric data which can each have their own resolution defined. For example if the data is 99.123 with a resolution of 2 then it should display 99.12. Similarly a data value of 99 and resolution 3 should be displayed as 99.000 (not 99). Is there a way to do this?

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

Edit:I should clarify, there are 95 TextBoxes on the current screen I'm working on, but I want every TextBox throughout the various screens in my program to display the correct number of decimal places. Now that I think about it, some of these are TextBoxes (like the screen I'm working on now) and some are DataGrids or ListViews, but if I can figure out how to get it working for TextBoxes I'm sure I can figure it out for the other controls as well.

编辑:我应该澄清一下,我正在处理的当前屏幕上有 95 个文本框,但我希望程序中各个屏幕中的每个文本框都显示正确的小数位数。现在我考虑了一下,其中一些是 TextBoxes(就像我现在正在处理的屏幕一样),一些是 DataGrids 或 ListViews,但是如果我能弄清楚如何让它为 TextBoxes 工作,我相信我可以弄清楚它也用于其他控件。

There's not much code to share in this case but I'll attempt to make it clearer:

在这种情况下没有太多代码可以共享,但我会尝试使其更清晰:

I have a View Model which contains the following properties (vb.net):

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

and in the XAML I have:

在 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 (my solution):It turns out that after walking away from the computer for a while, I came back to find a simple answer that was staring me in the face. Format the data in the view model!

EDIT2(我的解决方案):事实证明,在离开计算机一段时间后,我回来寻找一个简单的答案,它正盯着我的脸。格式化视图模型中的数据!

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

回答by Abe Heidebrecht

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

您应该StringFormatBinding. 您可以使用标准字符串格式自定义字符串格式

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

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

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

Edit for updated question

编辑更新的问题

So, if your ViewModeldefines 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 IMultiValueConverterwould need to take the value, and the precision, and output the formatted string. You'd be able to do this using String.Format.

所以,如果你ViewModel定义的精确度,我建议这样做的MultiBinding,和创建自己的IMultiValueConverter。这在实践中很烦人,从一个简单的绑定到一个需要扩展到 a 的绑定MultiBinding,但如果在编译时不知道精度,这几乎是你所能做的。您IMultiValueConverter需要获取值和精度,并输出格式化的字符串。您可以使用String.Format.

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

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

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

Any control that exposes a ContentStringFormatcan be used like this. Unfortunately, TextBoxdoesn't have anything like that.

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

回答by Manish Dubey

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

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

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

回答by Monali Pawar

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