[英]Xamarin: Get bound property of Entry.Text from event handler in code behind
[英]Setter of property bound to Entry.Text loops infinitely
这真让我抓狂。 我一直在寻找问题的根源几个小时,但我开始怀疑这不是我的逻辑问题......也许我错了。
我有一个简单的Entry 。 它的Text属性绑定到ViewModel中的double类型的属性。 同时,我订阅了Unfocused
Event ,它的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);
}
String.Format
尝试将小数点四舍五入到小数点后两位。 如果我给6.999
预期值应该是7.00
,但应用程序变得无响应。
<StackLayout>
<Entry Text="{Binding Weight}"
Unfocused="entry_Unfocused"/>
</StackLayout>
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";
}
}
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));
}
}
Unfocused
被解雇。谁能解释这里发生了什么,无论如何要解决这个问题?
我测试你的代码,调试它,我发现它会无限循环
set
{
if (_Weight != value)
{
_Weight = value;
OnPropertyChanged();
}
}
}
我认为这是因为您的Weight
属性是double
类型,它无法将其正确设置为string
,您可以尝试将 Weight 定义为字符串。
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"
设置时,这个值显然被解析为 double 然后发送到我的属性设置器。 实际上:
double _Weight = double.Parse("3.00"); // _Weight ends up having value 3!!!
所以entry.Text
和_Weight
总是有不同的值!!! 并且绑定尝试将_Weight
无限设置为3.00
,但所有_Weight
在设置器中获得的都是3
...
为了解决这个问题,我可以将其更改为十进制,而不是按照@LeoZhu-MSFT 的建议将我的属性_Weight
更改为String ,这是次优的(我仍然想使用我的Weight
属性执行数学运算)!
实际上:
decimal _Weight = decimal.Parse("3.00"); // _Weight has now value 3.00. As wanted!!!
因此,在我的视图 Model _Weight
和Weight
类型更改为十进制后,无限循环行为消失了: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}}" />
全部:)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.