问题描述
我希望在用户键入时有条件地过滤/更改Text
的{{1}}属性。 PreviewKeyDown
事件在wpf中的处理方式相同:在Entry
事件之前触发,该事件使控件可以在修改用户输入内容之前将其显示给用户,而稍后输入该内容时,则进行控制。
不幸的是,在Xamarin中不存在此类事件。下面是到目前为止我已经尝试过的一个示例(将所有内容放在代码后仅作为示例),但是却导致了堆栈溢出(在setter中的KeyDown
事件和Entry_TextChanged
之间反弹)。
我的问题不是纠正我的代码,而是一种最简单的方法来实现上述要求。
PS: 在setter上进行条件修改不是一种选择,因为它不是一个好的设计,并且不会重复使用。
MyPage.xaml
notifypropertychanged
MyPage.xaml.cs
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:AppTest"
x:Class="AppTest.MainPage">
<StackLayout>
<Entry Text="{Binding entrystr}"
Keyboard="Numeric"
TextChanged="Entry_TextChanged"/>
</StackLayout>
</ContentPage>
解决方法
我不太喜欢在二传手中进行设计,但是似乎没有太多选择,我试图使其更加灵活/可重复使用。
ViewModelBase.cs
public abstract class ViewModelBase: INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void SetProperty<T>(ref T field,T value,Func<T,T,T> PrefilterMethod = null,[CallerMemberName] string name = null)
{
if (!Equals(field,value))
{
if (PrefilterMethod != null)
field = PrefilterMethod.Invoke(field,value);
else
field = value;
OnPropertyChanged(name);
}
}
protected void OnPropertyChanged([CallerMemberName] string name = null) =>
PropertyChanged?.Invoke(this,new PropertyChangedEventArgs(name));
}
MainPageViewModel.cs
public class MainPageViewModel : ViewModelBase
{
private string _EntryStr;
public string EntryStr
{
get => _EntryStr;
set => SetProperty(ref _EntryStr,value,Setter_Filter);
}
private string Setter_Filter(string oldstr,string newstr)
{
float OldValueFloat,NewValueFloat;
float.TryParse(oldstr,out OldValueFloat);
float.TryParse(newstr,out NewValueFloat);
return NewValueFloat > 5 ?
OldValueFloat.ToString() : NewValueFloat.ToString();
}
MainPage.cs
public MainPage()
{
InitializeComponent();
BindingContext = new MainPageViewModel();
}
当然不再需要TextChanged
事件。