行为未触发OnPropertyChanged

时间:2017-05-11 07:23:22

标签: c# xamarin

我有检查电子邮件地址的自定义行为

using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using Xamarin.Forms;

namespace AllTheSame.Behaviors.Validator
{
    public class EmailValidatorBehavior : Behavior<Entry>
    {
        private static readonly BindablePropertyKey IsValidPropertyKey = BindableProperty.CreateReadOnly("IsValid", typeof(bool), typeof(EmailValidatorBehavior), default(bool), BindingMode.TwoWay);

        public static readonly BindableProperty IsValidProperty = IsValidPropertyKey.BindableProperty;

        public bool IsValid
        {
            get => (bool) GetValue(IsValidProperty);
            private set => SetValue(IsValidPropertyKey, value);
        }

        protected override void OnAttachedTo(Entry bindable)
        {
            base.OnAttachedTo(bindable);
            bindable.TextChanged += HandleTextChanged;
        }

        private void HandleTextChanged(object sender, TextChangedEventArgs e)
        {
            try
            {
                IsValid = Regex.IsMatch(e.NewTextValue, "^(?(\")(\".+?(?<!\\\\)\"@)|(([0-9a-z]((\\.(?!\\.))|[-!#\\$%&\'\\*\\+/=\\?\\^`\\{\\}\\|~\\w])*)(?<=[0-9a-z])@))(?(\\[)(\\[(\\d{1,3}\\.){3}\\d{1,3}\\])|(([0-9a-z][-\\w]*[0-9a-z]*\\.)+[a-z0-9][\\-a-z0-9]{0,22}[a-z0-9]))$");
            }
            catch
            {
                IsValid = false;
            }
            finally
            {
                ((Entry) sender).TextColor = IsValid ? Color.Default : Color.Red;
            }
        }

        protected override void OnDetachingFrom(Entry bindable)
        {
            base.OnDetachingFrom(bindable);
            bindable.TextChanged -= HandleTextChanged;
        }
    }
}

我在我的XAML页面中使用了这个

...
<ContentPage.BindingContext>
    <viewModels:RegisterViewModel />
</ContentPage.BindingContext>
...
<Entry Placeholder="Email" Text="{Binding Email}">
    <Entry.Behaviors>
        <validator:EmailValidatorBehavior x:Name="EmailValidatorBehavior" IsValid="{Binding IsEmailValid}"/>
    </Entry.Behaviors>
</Entry>

我的页面绑定到我的RegisterViewModel,我的中有一个属性“IsEmailValid”。

public bool IsEmailValid
{
    get => _isEmailValid;
    set
    {
        _isEmailValid = value;
        OnPropertyChanged();
        SignUpCommand.ChangeCanExecute();
    }
}

private bool _isEmailValid;

问题是,当我更改条目的文本时,行为中的“HandleTextChanged”方法被执行,但我的“RegisterViewModel”中的属性“IsEmailValid”的值不会更改。我可能在这里做错了但我无法弄明白。我尝试在我的行为中使用BindableProperty.Create,但没有任何改变。

你能帮我吗?

2 个答案:

答案 0 :(得分:0)

您是否需要INotifyPropertyChanged? 这是一个例子:

public class Data : INotifyPropertyChanged
{
// boiler-plate
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
    PropertyChangedEventHandler handler = PropertyChanged;
    if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
protected bool SetField<T>(ref T field, T value, string propertyName)
{
    if (EqualityComparer<T>.Default.Equals(field, value)) return false;
    field = value;
    OnPropertyChanged(propertyName);
    return true;
}

// props
private string name;
public string Name
{
    get { return name; }
    set { SetField(ref name, value, "Name"); }
}

}

答案 1 :(得分:0)

我首先尝试将IsValid绑定设置为双向。

<validator:EmailValidatorBehavior ... IsValid="{Binding IsEmailValid, Mode=TwoWay}"/>

如果这不起作用,我会尝试在可绑定属性上添加回调

public static readonly BindableProperty IsValidProperty = 
BindableProperty.CreateReadOnly("IsValid", typeof(bool), typeof(EmailValidatorBehavior), null, 
propertyChanged: OnIsValidChanged);

static void OnIsValidChanged (BindableObject bindable, object oldValue, object newValue)
{
    // Property changed implementation goes here
}