用户在键入类似于wpf中的PreviewKeyDown时,修改条目的Text属性 [英] Modify Text property of an Entry while user is typing similar to PreviewKeyDown from wpf
问题描述
我希望在用户键入时有条件地过滤/更改Entry
的Text
属性. PreviewKeyDown
事件在wpf中起作用:在KeyDown
事件之前触发,它使控件能够修改用户的输入,然后再显示给用户,而稍后输入.
I am looking to conditionally filter/alter the Text
property of an Entry
while user is typing. The same way PreviewKeyDown
event does in wpf: fired before the KeyDown
event, which gives control to modify the user's input before being displayed to user while the later is typing.
不幸的是,在Xamarin中不存在此类事件.下面是我到目前为止尝试过的一个示例(将所有内容放在代码后仅作为示例),但导致了堆栈溢出(在setter中的Entry_TextChanged
事件和notifypropertychanged
之间反弹).
Unfortunately in Xamarin such event does not exist. Below is a sample (put everything in code-behind only for sample) of what I have tried so far, but caused a stack overflow (bouncing between Entry_TextChanged
event and notifypropertychanged
in setter).
我的问题不是纠正我的代码,而是一种最简单的方法来实现上述要求.
My question is not to correct my code, but a clean way to achieve the described requirement on top.
PS: 在setter上进行条件修改不是一种选择,因为它不是一个好的设计,并且将无法重用.
PS: Doing the conditional modification on the setter is not an option as it is not a good design, and won't be reusable.
MyPage.xaml
MyPage.xaml
<?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>
MyPage.xaml.cs
MyPage.xaml.cs
using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using Xamarin.Forms;
namespace AppTest
{
public partial class MainPage : ContentPage, INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private string _EntryStr;
public string EntryStr
{
get { return _EntryStr; }
set
{
if(Equals(_EntryStr, value))
{
_EntryStr = value;
OnPropertyChanged();
}
}
}
public void OnPropertyChanged([CallerMemberName] string name = null) =>
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
public MainPage()
{
InitializeComponent();
BindingContext = this;
}
private void Entry_TextChanged(object sender, TextChangedEventArgs e)
{
float OldValueFloat, NewValueFloat;
float.TryParse(e.OldTextValue, out OldValueFloat);
float.TryParse(e.NewTextValue, out NewValueFloat);
((sender as Entry).BindingContext as MainPage).EntryStr = NewValueFloat > 5 ?
OldValueFloat.ToString() : NewValueFloat.ToString();
}
}
}
推荐答案
我不太喜欢将设计器放入设计器中,但是似乎没有太多选择,我试图使其更加灵活/可重复使用的.
I don't really like the design by making it in the setter but it seems there is not a lot of options, I tried to make it more flexible/reusable.
ViewModelBase.cs
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
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
MainPage.cs
public MainPage()
{
InitializeComponent();
BindingContext = new MainPageViewModel();
}
当然,不再需要TextChanged
事件.
这篇关于用户在键入类似于wpf中的PreviewKeyDown时,修改条目的Text属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!