Xamarin.Forms覆盖EditText方法导致无限循环

时间:2016-08-26 16:54:22

标签: c# xamarin.forms xamarin.forms.entry

我有两个自定义条目:

  • MaxLengthEntry : Entry
  • BannedCharactersEntry : MaxLengthEntry

问题是当用户输入允许且超过条目最大长度的字符时会发生无限循环。

{X}中添加了BannedCharactersEntry,如下所示:

<local:BannedCharactersEntry BannedCharacters="369" Text="1" Keyboard="Numeric" MaxLength="1" />


MaxLengthEntry 类:

class MaxLengthEntry : Entry
{
    public MaxLengthEntry()
    {
        base.TextChanged += EditText;
    }

    public virtual void EditText(object sender, TextChangedEventArgs args)
    {
        Entry e = sender as Entry;
        String val = e.Text;

        if (string.IsNullOrEmpty(val))
            return;

        if (Uppercase)
            val = val.ToUpper();

        if (MaxLength > 0 && val.Length > MaxLength)
        {
            val = val.Remove(val.Length - 1);
        }
        e.Text = val;
        Debug.WriteLine("MAX: " + val);
    }

    public static readonly BindableProperty UppercaseProperty = BindableProperty.Create<MaxLengthEntry, bool>(p => p.Uppercase, false);

    public bool Uppercase
    {
        get
        {
            return (bool)GetValue(UppercaseProperty);
        }
        set
        {
            SetValue(UppercaseProperty, value);
        }
    }

    public static readonly BindableProperty MaxLengthProperty = BindableProperty.Create<MaxLengthEntry, int>(p => p.MaxLength, 0);

    public int MaxLength
    {
        get
        {
            return (int)GetValue(MaxLengthProperty);
        }
        set
        {
            SetValue(MaxLengthProperty, value);
        }
    }
}

BannedCharactersEntry 类:

class BannedCharactersEntry : MaxLengthEntry
{
    public static readonly BindableProperty BannedCharactersProperty =
  BindableProperty.Create("BannedCharacters", typeof(string), typeof(BannedCharactersEntry), null);

    public string BannedCharacters
    {
        get { return (string)GetValue(BannedCharactersProperty); }
        set { SetValue(BannedCharactersProperty, value); }
    }

    public BannedCharactersEntry() : base()
    {

    }

    public override void EditText(object sender, TextChangedEventArgs args)
    {
        base.EditText(sender, args);

        Entry e = sender as Entry;
        String val = e.Text;

        Debug.WriteLine("BANNED: " + val);

        if (string.IsNullOrEmpty(val))
            return;

        foreach (char c in BannedCharacters)
        {
            if (val[val.Length - 1] == c)
            {
                val = val.Remove(val.Length - 1);
                break;
            }
        }

        e.Text = val;
    }
}

BannedCharactersEntry的初始值为1.然后按2.
输出如下:

MAX:1 禁止:12
MAX:1 禁止:1
MAX:1 禁止:12
MAX:1 禁止:1
等...

我不知道为什么连续调用EditText方法或为什么 BANNED 输出为12。

2 个答案:

答案 0 :(得分:0)

您可以将Text属性绑定到您的viewmodel,并从ViewModel属性中删除该字符。

您也可以尝试附加override TextChanged中的BannedCharacterEntry事件,而不是base.EditText

此外,您在覆盖功能开始时调用base.EditText将更改文本,但在继续执行时,您使用原始值而不是更改的值。您可以在被覆盖的函数结束时调用EditText

而且,您无需将import UIKit import AVFoundation class ViewController: UIViewController { var audioPlayer = AVAudioPlayer() var player1 = AVAudioPlayer() func playsound(sender: AnyObject){ let soundUrl = NSBundle.mainBundle().URLForResource("fsfa", withExtension: "mp3")! // or m4a do { try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryAmbient) try AVAudioSession.sharedInstance().setActive(true) player1 = try AVAudioPlayer(contentsOfURL: soundUrl) player1.numberOfLoops = -1 player1.prepareToPlay() player1.play() } catch _ { return print("sound file not found") } } func stopsound1(sender: AnyObject){ let soundUrl = NSBundle.mainBundle().URLForResource("dsd", withExtension: "mp3")! do { try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryAmbient) try AVAudioSession.sharedInstance().setActive(true) player1 = try AVAudioPlayer(contentsOfURL: soundUrl) player1.stop() } catch _ { return print("sound file not found") } } 方法视为公开方式。它可以是私人的。如果要在两个构造函数中附加它。

答案 1 :(得分:0)

解决方案非常简单。感谢Rohit指出我正确的方向!

BannedCharactersEntry 类中的

EditText方法:

protected override void EditText(object sender, TextChangedEventArgs args)
    {
        Entry e = sender as Entry;
        String val = e.Text;

        if (string.IsNullOrEmpty(val))
            return;

        foreach (char c in BannedCharacters)
        {
            if (val[val.Length - 1] == c)
            {
                val = val.Remove(val.Length - 1);
                e.Text = val;
                return;
            }
        }

        base.EditText(sender, args);
    }

如果输入了禁止的字符,我需要做的就是从方法返回,因为如果在输入时删除被禁止的字符,则永远不会超过MaxLength

否则,通过MaxLengthEntry.EditText调用base.EditText。我不需要担心无限循环,因为文本被更改或调用base.EditText。从来没有。