用于测量单位的 wpf 字符串格式 c#

wpf string format c# for measurement units

我将 MVVM 模式与 Entity Framework 结合使用来创建应用程序。我有一个名为 ScaleRange 的实体,它具有以下属性:UpperRange(以克或毫克为单位,整数类型)、LowerRange(以克或毫克为单位,整数类型)和 Precision(以克或毫克为单位,小数类型)。我以克为单位将所有属性保存在数据库中(或者我应该?)。问题是当我需要在 DataGrid 中显示 ScaleRange 列表时,所有属性都以克表示(因为数据是从数据库中提取的)并且在某些情况下我更喜欢值为 0.0001(以克为单位)毫克以获得更好的外观(在这种情况下为 0.1)。是否有某种字符串格式,例如,如果值 < 0.01 比以毫克显示,否则以克显示?

这是 DataGrid 的代码(目前运行良好)

<DataGrid Grid.Column="3" Grid.Row="1" Grid.RowSpan="4" AutoGenerateColumns="False" ItemsSource="{Binding Scale.Ranges}" IsReadOnly="True">
        <DataGrid.Columns>
            <DataGridTextColumn Header="Upper range" Width="*" Binding="{Binding UpperRange, StringFormat={}{0}g}"></DataGridTextColumn>
            <DataGridTextColumn Header="Lower range" Width="*" Binding="{Binding LowerRange, StringFormat={}{0}g}"></DataGridTextColumn>
            <DataGridTextColumn Header="Precision" Width="*" Binding="{Binding Precision, StringFormat={}{0}g}"></DataGridTextColumn>
        </DataGrid.Columns>
    </DataGrid>

您可以为此使用一个转换器,here 是一个快速概览。
Convert 函数中,您可以添加逻辑来确定值是否 < 0.1 并相应地修改它。
您实际上并不需要 ConvertBack 函数,因为它是一种单向绑定。

如果让值转换器 class 派生自 MarkupExtension ( YourConverter : MarkupExtension, IValueConverter) 并像这样覆盖 ProvideValue 函数

public override object ProvideValue(IServiceProvider serviceProvider)
{
     return this;
} 

您可以将 XAML 代码中的集成简化为 {Binding Converter={conv:YourConverter},而不必先将转换器定义为资源。
您还必须添加对转换器命名空间的引用,在我的示例中是 conv:(例如 xmlns:conv="clr-namespace:Content.Common.Converter")。

我创建了这个适用于单位前缀 G、M、K、m、μ、n 的转换器。

它还没有经过彻底的测试,所以如果有任何问题请告诉我,并仔细检查您的值是否符合预期。

class GramToAppropriateUnitPrefixConverter : IValueConverter
{
    private List<string> unitsPrefix = new List<string>() //unit prefixes scalings by *10^3 in order, where the middle value is = *10^0
    {
        "G",
        "M",
        "k",
        "",
        "m",
        "μ",
        "n"
    };

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if(value is double number)
        {
            string numAsString;
            int sigFigs = 3;
            string unit = "g";
            int noPrefixIndex = (unitsPrefix.Count / 2);
            int unitsPrefixIndex = noPrefixIndex;

            numAsString = number.ToString("G" + sigFigs.ToString()).Replace("+", ""); //Convert to $sigFigs number of significant figures
            string[] numberStandForm = numAsString.Split('E'); //Convert to standard form (number = [0] * 10^[1])

            if (numberStandForm.Count() == 2)
            {
                unitsPrefixIndex = noPrefixIndex +(int.Parse(numberStandForm[1]) / 3);

                //Check the index is not out the range of the list
                if (unitsPrefixIndex < 0)
                    unitsPrefixIndex = 0;
                else if (unitsPrefixIndex > unitsPrefix.Count - 1)
                    unitsPrefixIndex = unitsPrefix.Count - 1;

                //Change the standard form number so it is in the form ->   number * 10^(multipul of 3)
                var power = int.Parse(numberStandForm[1]) + ((unitsPrefixIndex - noPrefixIndex) * 3);
                string numberStr = (double.Parse(numberStandForm[0]) * Math.Pow(10, power)).ToString();
            }

            numAsString = numberStandForm[0] + unitsPrefix[unitsPrefixIndex] + unit;

            return numAsString;
        }

        return Binding.DoNothing;
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }

}