属性 的 Setter 绑定到 Entry.Text 无限循环
Setter of property bound to Entry.Text loops infinitely
这让我发疯。几个小时以来我一直在寻找问题的根源,但我开始怀疑这不是我逻辑上的问题......也许我错了。
问题描述
我有一个简单的 条目。它的 Text 属性 绑定到 ViewModel[=81 中类型为 double 的 属性 =].同时我订阅了 Unfocused
Event 其 EventHandler 只是将 entry.Text
属性 设置为"1.0"
(实际上我可以重现 x.y0 的问题,即最后一位为 0 的任何小数)。如果现在我在 Entry 中写入任何内容(“1”或“1.”或“1.0”除外!!!)并保留 Entry (通过点击外部或点击完成)以便 Unfocused
被触发,App 变得没有响应。
注意:我知道在事件处理程序中设置entry.Text = 1.0
听起来有点奇怪。事实上,我是通过尝试按如下方式格式化 entry.Text
值而遇到此问题的。
if (double.TryParse(entry.Text, out double result))
{
entry.Text = String.Format("{0:F2}", result);
}
String.Format
试图将小数点四舍五入到两位小数。如果我给 6.999
期望值应该是 7.00
,但是 App 变得没有响应。
重现问题的步骤
- 创建空白Xamarin.Forms项目。
- 删除 MainPage.xaml 文件中的默认 Label 以包含以下 Entry,相反:
<StackLayout>
<Entry Text="{Binding Weight}"
Unfocused="entry_Unfocused"/>
</StackLayout>
- 在后面的代码中添加下面的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";
}
}
- 像这样创建 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));
}
}
- 运行 应用程序并在 Entry.
中输入任何内容
- 保留 条目 以便
Unfocused
被解雇。
我的系统配置:
- Visual Studio 诉 16.3.8
- Xamarin.Forms 4.2.0.709249
- Android 8
谁能解释一下这里发生了什么,以及如何解决这个问题?
我测试了你的代码,并调试了它,我发现它会在
中无限循环
set
{
if (_Weight != value)
{
_Weight = value;
OnPropertyChanged();
}
}
}
我认为是因为你的Weight
属性是double
类型,所以不能正确设置为string
,你可以尝试将权重定义为字符串.
private string _Weight;
public string Weight
{
get => _Weight;
set
{
if (_Weight != value)
{
_Weight = value;
OnPropertyChanged();
}
}
}
这可能是因为您的未聚焦处理程序使用输入的值设置条目导致循环。
private void entry_Unfocused(object sender, FocusEventArgs e)
{
((Entry)sender).Text = "1.0";
}
我找到问题的根源了!
感谢@LeoZhu-MSFT 的见解!
问题是,当设置 entry.Text = "3.00"
时,这个值显然被解析为双倍,然后发送到我的 属性 setter。事实上:
double _Weight = double.Parse("3.00"); // _Weight ends up having value 3!!!
所以 entry.Text
和 _Weight
总是有不同的值!!!并且 绑定 试图将 _Weight
无限期地设置为 3.00
,但是 setter 中的所有 _Weight
都是 3
。 ..
为了解决这个问题,而不是按照@LeoZhu-MSFT 的建议将我的 属性 _Weight
更改为 String,这是次优的(我还是想用我的Weight
属性!)进行数学运算,我可以改成十进制!!!
事实上:
decimal _Weight = decimal.Parse("3.00"); // _Weight has now value 3.00. As wanted!!!
因此,在我将 _Weight
和 Weight
类型更改为 decimal 之后,在我的 View Model 中,无限循环行为消失了:D
我认为解决此问题的最佳方法是使用转换器
public class DecimalConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (value is decimal)
return value.ToString();
return value;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (decimal.TryParse(value as string, out var dec))
return dec;
return value;
}
}
用法
<Entry Text="{Binding Weight, Converter={StaticResource DecimalConverter}}" />
全部:)
这让我发疯。几个小时以来我一直在寻找问题的根源,但我开始怀疑这不是我逻辑上的问题......也许我错了。
问题描述
我有一个简单的 条目。它的 Text 属性 绑定到 ViewModel[=81 中类型为 double 的 属性 =].同时我订阅了 Unfocused
Event 其 EventHandler 只是将 entry.Text
属性 设置为"1.0"
(实际上我可以重现 x.y0 的问题,即最后一位为 0 的任何小数)。如果现在我在 Entry 中写入任何内容(“1”或“1.”或“1.0”除外!!!)并保留 Entry (通过点击外部或点击完成)以便 Unfocused
被触发,App 变得没有响应。
注意:我知道在事件处理程序中设置entry.Text = 1.0
听起来有点奇怪。事实上,我是通过尝试按如下方式格式化 entry.Text
值而遇到此问题的。
if (double.TryParse(entry.Text, out double result))
{
entry.Text = String.Format("{0:F2}", result);
}
String.Format
试图将小数点四舍五入到两位小数。如果我给 6.999
期望值应该是 7.00
,但是 App 变得没有响应。
重现问题的步骤
- 创建空白Xamarin.Forms项目。
- 删除 MainPage.xaml 文件中的默认 Label 以包含以下 Entry,相反:
<StackLayout>
<Entry Text="{Binding Weight}"
Unfocused="entry_Unfocused"/>
</StackLayout>
- 在后面的代码中添加下面的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";
}
}
- 像这样创建 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));
}
}
- 运行 应用程序并在 Entry. 中输入任何内容
- 保留 条目 以便
Unfocused
被解雇。
我的系统配置:
- Visual Studio 诉 16.3.8
- Xamarin.Forms 4.2.0.709249
- Android 8
谁能解释一下这里发生了什么,以及如何解决这个问题?
我测试了你的代码,并调试了它,我发现它会在
中无限循环set
{
if (_Weight != value)
{
_Weight = value;
OnPropertyChanged();
}
}
}
我认为是因为你的Weight
属性是double
类型,所以不能正确设置为string
,你可以尝试将权重定义为字符串.
private string _Weight;
public string Weight
{
get => _Weight;
set
{
if (_Weight != value)
{
_Weight = value;
OnPropertyChanged();
}
}
}
这可能是因为您的未聚焦处理程序使用输入的值设置条目导致循环。
private void entry_Unfocused(object sender, FocusEventArgs e)
{
((Entry)sender).Text = "1.0";
}
我找到问题的根源了!
感谢@LeoZhu-MSFT 的见解!
问题是,当设置 entry.Text = "3.00"
时,这个值显然被解析为双倍,然后发送到我的 属性 setter。事实上:
double _Weight = double.Parse("3.00"); // _Weight ends up having value 3!!!
所以 entry.Text
和 _Weight
总是有不同的值!!!并且 绑定 试图将 _Weight
无限期地设置为 3.00
,但是 setter 中的所有 _Weight
都是 3
。 ..
为了解决这个问题,而不是按照@LeoZhu-MSFT 的建议将我的 属性 _Weight
更改为 String,这是次优的(我还是想用我的Weight
属性!)进行数学运算,我可以改成十进制!!!
事实上:
decimal _Weight = decimal.Parse("3.00"); // _Weight has now value 3.00. As wanted!!!
因此,在我将 _Weight
和 Weight
类型更改为 decimal 之后,在我的 View Model 中,无限循环行为消失了:D
我认为解决此问题的最佳方法是使用转换器
public class DecimalConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (value is decimal)
return value.ToString();
return value;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (decimal.TryParse(value as string, out var dec))
return dec;
return value;
}
}
用法
<Entry Text="{Binding Weight, Converter={StaticResource DecimalConverter}}" />
全部:)