c# - 在用户键入类似于来自 wpf 的 PreviewKeyDown 时修改条目的 Text 属性
问题描述
我希望有条件地过滤/更改用户正在键入的Text
属性。Entry
与 wpf 中的 event相同PreviewKeyDown
:在事件之前触发KeyDown
,它可以控制在显示给用户之前修改用户的输入,而后者正在输入。
不幸的是,在 Xamarin 中这样的事件并不存在。下面是我迄今为止尝试过的一个示例(将所有内容放在代码隐藏中仅用于示例),但导致堆栈溢出(在Entry_TextChanged
事件和notifypropertychanged
设置器之间弹跳)。
我的问题不是更正我的代码,而是一种干净的方式来实现上面描述的要求。
PS:对setter进行条件修改不是一种选择,因为它不是一个好的设计,并且不会可重用。
我的页面.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>
我的页面.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();
}
}
}
解决方案
我不太喜欢在 setter 中制作的设计,但似乎没有很多选择,我试图让它更灵活/可重用。
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();
}
主页.cs
public MainPage()
{
InitializeComponent();
BindingContext = new MainPageViewModel();
}
当然TextChanged
,不再需要事件。
推荐阅读
- scala - 如何使用火花将列添加到json字段中
- angular - EventSource 动态绑定变量
- c - malloc 和 memcpy 的漏洞
- osdev - 将引导加载程序函数加载到内核中
- kotlin - 如何在 Kotlin 中写做笔记?
- javascript - 如何动态更新文本/javascript src(jotform javascript embed)
- angular - “找不到具有 id 的列”,但该列存在
- node.js - 无法迁移带有 db:migrate 续集的 postgres
- javascript - 你能做一个可变的href,而不是一个按钮,只有一个文本框
- c# - 将 json 反序列化为 c# 对象