如何在按钮

时间:2017-02-15 23:26:08

标签: c# xamarin.forms

我正在尝试实现验证控制。

我有一个页面,其中有一个条目和一个ok 按钮

该条目是电子邮件输入,我实施了行为,以向用户显示他的输入是否良好。我想将按钮的 IsEnabled 属性绑定到行为的 IsValid 属性。

以下是行为代码:

public class EmailValidatorBehavior : Behavior<Entry>
{
    const string emailRegex = @"^(?("")("".+?(?<!\\)""@)|(([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]))$";


    public static BindableProperty IsValidProperty = BindableProperty.Create("IsValid", typeof(bool), typeof(EmailValidatorBehavior), false);

    public bool IsValid
    {
        get { return (bool)base.GetValue(IsValidProperty); }
        private set { base.SetValue(IsValidProperty, value); }
    }

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

    void HandleTextChanged(object sender, TextChangedEventArgs e)
    {
        bool IsValid = false;
        IsValid = (Regex.IsMatch(e.NewTextValue, emailRegex, RegexOptions.IgnoreCase, TimeSpan.FromMilliseconds(250)));
        ((Entry)sender).TextColor = IsValid ? Color.Default : Color.Red;
    }

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

在页面中,我有这样的行为。 只有当电子邮件验证正则表达式时,颜色变化才会恢复正常

_emailEntry.Behaviors.Add(new EmailValidatorBehavior());

另外,我的页面有一个 bindingContext ,它是一个视图模型。据我所知,我将在这里做我的逻辑绑定。我看到我必须在IsValidProperty上监听属性更改事件,但我无法解决如何实现它。即使我在xamarin的网站上阅读了很多文档,特别是在行为和创建可绑定属性的情况下,我仍然不清楚绑定和 bindableProperty 。我已经开始了:

在页面中:

     var behavior = new EmailValidatorBehavior();
        //Binding context is LandingViewModel 
        behavior.SetBinding(EmailValidatorBehavior.IsValidProperty, "IsValid");
        _okButton.SetBinding(MR.Gestures.Button.IsEnabledProperty, "IsEnabled");
        _emailEntry.Behaviors.Add(behavior);

以下是视图模型:

public class LandingViewModel : BaseViewModel
{

    private bool _isEnabled;
    private bool _isValid;

    public bool IsEnabled
    {
        get { return _isEnabled; }
        set
        {
            if (_isEnabled == value) return;
            _isEnabled = value;
            OnPropertyChanged("IsEnabled");
        }   
    }

    public bool IsValid
    {
        get { return _isValid; }
        set
        {
            Debug.WriteLine(_isValid);
            if (_isValid == value) return;
            _isValid = value;
            IsEnabled = _isValid;
            Debug.WriteLine(_isValid);
            OnPropertyChanged("IsValid");
        }
    }

我不高兴,我看到我显然遗失了什么,却看不出来......

非常感谢你。

3 个答案:

答案 0 :(得分:3)

查看您添加的Debug.WriteLine(),我猜测绑定未设置IsValid属性。

这是因为您没有设置DefaultBindingMode的{​​{1}},或者因为您没有设置BindableProperty本身的BindingMode。因此绑定默认为Binding,这意味着在更改视图模型时会修改您的行为OneWay,而不是相反。

以这种方式创建IsValid

BindableProperty

这应该有用。

如果我可以的话还有一些补充说明:

1。不需要浏览ViewModel

您可以将public static BindableProperty IsValidProperty = BindableProperty.Create("IsValid", typeof(bool), typeof(EmailValidatorBehavior), false, BindingMode.TwoWay); Entry属性直接绑定到行为IsEnabled属性。

IsValid

如果您这样做,行为将成为绑定的来源,您不必创建var behavior = new EmailValidatorBehavior(); _okButton.SetBinding(MR.Gestures.Button.IsEnabledProperty, new Binding("IsEnabled", source: behavior)); _emailEntry.Behaviors.Add(behavior); ,您只需实施BindableProperty

2。确保您永远不会在INotifyPropertyChanged个实例

之间共享行为

如果您在样式中共享此行为,则将重用相同的实例,并且它将无法按预期工作。

答案 1 :(得分:1)

您的视图模型中没有IsEnabled属性,因此行OnPropertyChanged("IsEnabled");根本不会做任何事情。我认为您需要做的是将SetIsEnabledButton属性的名称更改为IsEnabled,并将行_isEnabled = _isValid;更改为IsEnabled = _isValid;。这样设置IsValid时,它会将控件转移到IsEnabled setter,然后会自动引发属性更改通知。

如果你仍然无法让它工作,请回到这里。

答案 2 :(得分:0)

我已经发现它能够正常工作,而且由于@Stephane Delcroix的帖子,我不需要任何视图模型。

我仍然对@Stephane Delcroix建议之后的行为拥有可绑定属性。

public static BindableProperty IsValidProperty = BindableProperty.Create("IsValid", typeof(bool), typeof(EmailValidatorBehavior), false, BindingMode.TwoWay);

要在isValid属性上绑定我的按钮,我写道:

_okButton.SetBinding(IsEnabledProperty,
                new Binding(EmailValidatorBehavior.IsValidProperty.PropertyName));

&#34;参考PropertyName而不是&#34; Value&#34;这是一个很好的做法。喜欢&#34; IsValid&#34;,以这种方式避免字符串中的任何拼写错误,并且编译器和完成都避免错误&#34;。

我在行为上设置了我的按钮的bindingContext:

 _okButton.BindingContext = _emailBehavior;