用户在键入类似于wpf中的PreviewKeyDown时,修改条目的Text属性 [英] Modify Text property of an Entry while user is typing similar to PreviewKeyDown from wpf

查看:238
本文介绍了用户在键入类似于wpf中的PreviewKeyDown时,修改条目的Text属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我希望在用户键入时有条件地过滤/更改EntryText属性. 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆