【问题标题】:Xamarin.Forms Entry - Custom Behaviors and MVVMXamarin.Forms 条目 - 自定义行为和 MVVM
【发布时间】:2017-08-16 05:04:48
【问题描述】:

我想为我的 Xamarin Forms 项目添加一些验证。这些是一些非常基本的内容,例如:

  • 最小/最大字符串长度
  • 电子邮件格式
  • 密码确认

我在我的项目中使用 MVVM Light,因此,我没有在我的页面中使用代码。

我正在使用下面的代码,尝试将 Behavior 的值绑定到我的 ViewModel 中的属性。

EmailValidatorBehavior.cs:

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 readonly BindablePropertyKey IsValidPropertyKey = BindableProperty.CreateReadOnly("IsValid", typeof(bool), typeof(EmailValidatorBehavior), false);

        public static readonly BindableProperty IsValidProperty = IsValidPropertyKey.BindableProperty;

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

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

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

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

        }
    }

View.xaml:

<Entry 
    Placeholder="E-mail"
    Text="{Binding Path=User.email, Mode=TwoWay}"
    Keyboard="Email">

    <Entry.Behaviors>
        <EmailValidatorBehavior x:Name="emailValidator" IsValid="{Binding Path=IsEmailValid, Mode=TwoWay}" />
    </Entry.Behaviors>
</Entry>

ViewModel.cs:

private bool _IsEmailValid = false;
public bool IsEmailValid
{
    get
    {
        return _IsEmailValid;
    }
    set
    {
        _IsEmailValid = value;
        RaisePropertyChanged("IsEmailValid");
    }
}

IsEmailValid 的值永远不会改变,即使电子邮件是正确的并且行为的 IsValid 属性变为 true。有什么问题?

提前致谢。

【问题讨论】:

  • 你发现了吗?

标签: c# validation mvvm xamarin.forms


【解决方案1】:

除了 xaml 本地行为附件之外,您似乎已经正确设置了所有内容。您需要更改以下内容:

原始示例

<EmailValidatorBehavior x:Name="emailValidator" IsValid="{Binding Path=IsEmailValid, Mode=TwoWay}" />

更新代码

  <Entry Placeholder="testing">
      <Entry.Behaviors>
          <local:EmailValidatorBehavior></local:EmailValidatorBehavior>
      </Entry.Behaviors>
  </Entry>

输出
我在此示例中使用了您的自定义行为,并且一切正常。左侧显示IsValid = false,右侧显示IsValid = true

如果您对此有任何问题,请告诉我。干杯!

【讨论】:

    【解决方案2】:

    我也遇到了这个问题,找不到满意的答案,但似乎行为中的BindingContext 未设置为页面的BindingContext

    由于我不是这方面的专家,我认为会有更优雅的方法,但是;这似乎有效:

    首先,将您的页面命名为以后用作参考:

    <ContentPage x:Name="Root" etc, etc>
    

    然后,在您的行为中:将路径和来源设置为页面的绑定上下文:

    <Entry Text="{Binding RegistrationEmail}">
        <Entry.Behaviors>
             <connector:EmailValidatorBehavior 
                IsValid="{Binding Source={x:Reference Root}, 
                          Path=BindingContext.IsRegistrationEmailValid, Mode=OneWayToSource}"/>
        </Entry.Behaviors>        
    </Entry>
    

    顺便说一句,我认为使用Mode=OneWayToSource 更合适,因为您的可绑定属性是只读的。

    在视图模型中设置断点时,您会看到布尔值已更新。

    【讨论】:

    • 感谢您正确设置 BindingContext!
    猜你喜欢
    • 2015-09-01
    • 2017-08-14
    • 2011-12-02
    • 2016-01-11
    • 2019-01-13
    • 2018-07-20
    • 1970-01-01
    • 1970-01-01
    • 2022-01-23
    相关资源
    最近更新 更多