用双精度存储十进制数?使用 updatesourcetrigger 作为 PropertyChanged 的属性

问题描述 投票:0回答:4

我正在使用 WPF/MVVM。 我将 textbox.Text 绑定到视图模型中的可为空的双精度值。 UpdateSourceTrigger = PropertyChanged 而不是 Lostfocus。因此,当使用我正在使用的转换器内的 Double.Parse(textbox.Text) 输入每个数字时, double 属性将被更新。我在这里使用 PropertyChanged 和转换器,因为我需要进行一些其他验证检查。

我的问题是我需要输入“1.69”。 当我输入“1”时,它会作为“1”添加到属性中。 接下来我输入“.”,但它没有添加为“1”。因为 double.parse 将数字保存为“1”

所以我不能添加小数。请帮忙。预先感谢。

c# wpf xaml
4个回答
5
投票

如果您使用

StringFormat=\{0:n\}
,应该没问题。例如:

<TextBox Text="{Binding FooValue, UpdateSourceTrigger=PropertyChanged, 
                                               StringFormat=\{0:n\}}"/>

或者只使用转换器。例如:

<Window.Resources>        
   <helper:DoubleConverter x:Key="DoubleConverter" />
</Window.Resources>
...The code omitted for the brevity
<TextBox Text="{Binding Amount, UpdateSourceTrigger=PropertyChanged,       
                        Converter={StaticResource DoubleConverter}}"/>

DoubleConverter

public class DoubleConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
       return value;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
       // return an invalid value in case of the value ends with a point
       return value.ToString().EndsWith(".") ? "." : value;
    }
}

1
投票

如果输入的字符串以

0
结尾,您可以在转换之前附加
.


1
投票

我刚刚在这篇文章的评论中使用转换器做了一个测试应用程序:当 TextBox 绑定到 double 并输入小于 -1 的负数时出现问题,它对我来说效果很好。

我的视图模型:

class MainWindowViewModel
{

    private double? myDouble;
    public double? MyDouble
    {
        get { return myDouble; }
        set
        {
            myDouble = value;
        }
    }
}

我的测试主窗口:

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApplication1"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525"
        >
    <Window.Resources>
        <local:DecimalConverter x:Key="converter" />
    </Window.Resources>

    <Grid>
        <TextBox 
            x:Name="textBox" 
            HorizontalAlignment="Left" 
            Text="{Binding MyDouble, Mode=TwoWay,UpdateSourceTrigger=PropertyChanged, Converter={StaticResource converter}}"
            Height="23" 
            Margin="10,185,0,0" 
            TextWrapping="Wrap" 
            VerticalAlignment="Top" 
            Width="120"/>

        <TextBox 
            x:Name="textBox1" 
            HorizontalAlignment="Left" 
            Text="{Binding MyDouble}"
            Height="23" 
            Margin="10,248,0,0" 
            TextWrapping="Wrap" 
            VerticalAlignment="Top" 
            Width="120"/>

    </Grid>
</Window>

文本框 1 按预期从文本框更新。尝试一下 Avneesh 的转换器。


0
投票

这篇文章已有 7 年历史,但鉴于它仍然是一个问题,我想发布我的解决方案以及我对问题的理解。

问题是,当您使用 updatesourcetrigger=propertychanged 在框中键入时,输入每个字符后,应用程序将运行解析为双精度。问题是对于像“1”这样的东西。这是要解析的有效字符串,在您输入小数并清除小数后,它会立即返回“1”。

我解决这个问题的方法是绑定到一个字符串属性,该属性有两个支持字段。一个是双精度数,一个是字符串。

private double _doubleEntry;
private string _stringEntry;
public string StringEntry {
    get => _stringEntry;
    set {
        _stringEntry = value;
        if (double.TryParse(value, out double temp))
            _doubleEntry = temp;
        OnPropertyChanged(nameof(StringEntry));
}

这将始终返回用户输入的字符串,但仅在有效输入时存储双精度值。

如果您想显示 WPF 控件中 _doubleEntry 变量中的值,您需要将其 LostFocus 绑定到一个方法,该方法从 _doubleEntry 中获取值并将其分配给您的控件的相应字段。

所以你的 Xaml 看起来像这样。

<TextBox
    LostFocus="{Binding StringEntryLostFocus}"
    Text="{Binding StringEntry, UpdateSourceTrigger=PropertyChanged}" />

LostFocus 方法的代码是

public void StringEntryLostFocus(object sender, EventArgs e) {
    var tb = sender as System.Windows.Controls.TextBox;
    if (tb is null) return;
    tb.Text = _targetTempDouble.ToString();

请随时对我的回答发表反馈。这是我第一次关于堆栈溢出。

© www.soinside.com 2019 - 2024. All rights reserved.