绑定到 Entry.Text 的属性设置器无限循环

Dec*_*oth 5 c# double string.format xamarin.android xamarin.forms

这真让我抓狂。几个小时以来,我一直在寻找问题的根源,但我开始怀疑这不是我的逻辑问题......也许我错了。


问题描述

我有一个简单的Entry。它的文本属性绑定到与类型的属性视图模型。同时,我订阅了Unfocused 事件,EventHandler只是将entry.Text属性设置为"1.0"(实际上我可以重现 x.y0 的问题,即最终数字为 0 的任何小数)。如果现在我在条目中写入任何内容(“1”或“1”或“1.0”除外!!!)并离开条目(通过点击外部或点击完成)以便Unfocused触发,应用程序将变得无响应。

注意:我知道entry.Text = 1.0在事件处理程序中设置听起来有点奇怪。事实是,我通过尝试entry.Text按如下方式格式化值时遇到了这个问题。

if (double.TryParse(entry.Text, out double result))
{
    entry.Text = String.Format("{0:F2}", result);
}
Run Code Online (Sandbox Code Playgroud)

String.Format尝试将小数四舍五入到两位小数。如果我给出6.999的预期值应该是7.00,但应用程序反而变得无响应。


重现问题的步骤

  1. 创建空白的Xamarin.Forms 项目
  2. 删除默认标签MainPage.xaml中文件以包括以下条目,而不是:
<StackLayout>
    <Entry Text="{Binding Weight}"
    Unfocused="entry_Unfocused"/>
</StackLayout>
Run Code Online (Sandbox Code Playgroud)
  1. 在后面的代码中添加下面的EventHandler并设置BindingContext页面的属性如下:
public partial class MainPage : ContentPage
{
    public MainPage()
    {
        InitializeComponent();
    }

    protected override void OnAppearing()
    {
        base.OnAppearing();
        BindingContext = new viewmodel();
    }

    private void entry_Unfocused(object sender, FocusEventArgs e)
    {
        ((Entry)sender).Text = "1.0";
    }

}
Run Code Online (Sandbox Code Playgroud)
  1. 创建ViewModel如下:
public class viewmodel : INotifyPropertyChanged
{
    public viewmodel()
    {
    }

    private double _Weight;
    public double Weight
    {
        get => _Weight;
        set
        {
            if (_Weight != value)
            {
                _Weight = value;
                OnPropertyChanged();
            }
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    private void OnPropertyChanged([CallerMemberName] String propertyName = "")
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}
Run Code Online (Sandbox Code Playgroud)
  1. 运行应用程序并在Entry 中输入任何内容。
  2. 离开条目以便Unfocused被解雇。

我的系统配置:

  • Visual Studio v. 16.3.8
  • Xamarin.Forms 4.2.0.709249
  • 安卓 8

任何人都可以解释这里发生了什么,无论如何要解决这个问题?

Dec*_*oth 0

我找到了问题的根源!

感谢@LeoZhu-MSFT 的见解!

问题是,当entry.Text = "3.00"设置时,该值显然会被解析为双倍,然后发送到我的属性设置器。实际上:

double _Weight = double.Parse("3.00"); // _Weight ends up having value 3!!! 
Run Code Online (Sandbox Code Playgroud)

所以entry.Text总是_Weight有不同的价值观!并且绑定尝试无限期地设置_Weight3.00但所有_Weight进入设置器的内容都是3......

为了解决这个问题,我可以将其更改_Weight十进制,而不是按照@LeoZhu-MSFT的建议将我的属性更改为字符串,这是次优的(我仍然想用我的属性执行数学运算Weight)!

实际上:

decimal _Weight = decimal.Parse("3.00"); // _Weight has now value 3.00. As wanted!!!
Run Code Online (Sandbox Code Playgroud)

因此,在我在视图模型_Weight中更改并Weight输入十进制后,无限循环行为消失了:D