- Hands-On Mobile Development with .NET Core
- Can Bilgin
- 652字
- 2021-06-24 13:55:40
Creating behaviors
Behaviors are an eloquent use of the decorator pattern, allowing the developers to modify the Xamarin.Forms controls without having to create derived controls.
A simple example of creating a behavior would be to implement a validation behavior in our LoginView. As you may remember, we actually used the Command.CanExecute delegate to validate our fields. In this example, we will separate the validators for the email field and the password field. This way, we can allow the UI to give feedback to the user as a result of an incorrect entry. This would be more user-friendly than only disabling the login window. To set this up, follow these steps:
- First, we need to create a validation rule infrastructure, starting with the validation interface:
public interface IValidationRule<T>
{
string ValidationMessage { get; set; }
bool Validate (T value);
}
- A simple implementation of this rule would be required so that we can check whether we have a short validation message stating that the field is a required field:
public class RequiredValidationRule : IValidationRule<string>
{
public string ValidationMessage { get; set; } = "This field is
a required field";
public bool Validate (string value)
{
return !string.IsNullOrEmpty(value);
}
}
- Now, we can create our validation behavior for the Entry field, which will make use of any given validation rule (starting with RequiredValidationRule, which we just implemented):
public class ValidationBehavior : Behavior<Entry>
{
protected override void OnAttachedTo(Entry bindable)
{
base.OnAttachedTo(bindable);
bindable.TextChanged += ValidateField;
}
protected override void OnDetachingFrom(Entry bindable)
{
base.OnDetachingFrom(bindable);
bindable.TextChanged -= ValidateField;
}
private void ValidateField(object sender, TextChangedEventArgs
args)
{
if (sender is Entry entry)
{
// TODO:
}
}
}
In this implementation, the OnAttachedTo and OnDetachingFrom methods are the crucial access points and the teardown logic implementations. In this case, when the behavior is attached to a target control, we are subscribing to the TextChanged event, and when the behavior is removed, we are unsubscribing from the event so that undesired memory leak issues are avoided.
- The next order of business will be to implement a bindable property for the validation rule so that the validation rules are dictated by the view model (or another business logic module), decoupling it from the view:
public static readonly BindableProperty ValidationRuleProperty =
BindableProperty.CreateAttached("ValidationRule", typeof(IValidationRule<string>), typeof(ValidationBehavior), null);
public static readonly BindableProperty HasErrorProperty =
BindableProperty.CreateAttached("HasError", typeof(bool), typeof(ValidationBehavior), false, BindingMode.TwoWay);
public IValidationRule<string> ValidationRule
{
get { return this.GetValue(ValidationRuleProperty) as IValidationRule<string>; }
set { this.SetValue(ValidationRuleProperty, value); }
}
public bool HasError
{
get { return (bool) GetValue(HasErrorProperty); }
set { SetValue(HasErrorProperty, value); }
}
- Now that we have an outlet for the validation rule and an output field (so that we can attach additional UX logic to it), we can implement the validate method:
private void ValidateField(object sender, TextChangedEventArgs
args)
{
if (sender is Entry entry && ValidationRule != null)
{
if (!ValidationRule.Validate(args.NewTextValue))
{
entry.BackgroundColor = Color.Crimson;
HasError = true;
}
else
{
entry.BackgroundColor = Color.White;
HasError = false;
}
}
}
- After adding the appropriate rule to the view model property (in this case, UserNameValidation), we can bind the behavior to the validation rule that's exposed from the view model and observe the entry field behavior according to the text input:
<Entry x:Name="usernameEntry" Placeholder="username" Text="{Binding UserName, Mode=OneWayToSource}" >
<Entry.Behaviors>
<behaviors:ValidationBehavior x:Name="UserNameValidation"
ValidationRule="{Binding
BindingContext.UserNameValidation,
Source={x:Reference RootView}}" />
</Entry.Behaviors>
</Entry>
Here, the main benefit is that we do not have to modify the Entry field, and the implemented behavior can be maintained as a separate module.
- To extend this implementation, we can add a validation error message label that will display in accordance with the HasError bindable property (anywhere on the page layout, as long as the UserNameValidation element is accessible):
<Label Text="UserName is required" FontSize="12" TextColor="Gray"
IsVisible="{Binding HasError, Source={x:Reference UserNameValidation}}"/>
- The outcome would look similar to the following:

- 角膜塑形鏡驗(yàn)配技術(shù)基礎(chǔ)篇
- 動態(tài)對比增強(qiáng)磁共振成像
- 甲狀腺疾病的核醫(yī)學(xué)診斷與治療
- 生命的探問:弗蘭克爾談生命的意義與價(jià)值
- 特殊醫(yī)學(xué)用途配方食品臨床應(yīng)用
- 出生缺陷與遺傳性疾病的檢驗(yàn)診斷
- 活血化瘀方藥臨床使用指南
- 放射診斷學(xué)讀片:北京協(xié)和醫(yī)院放射十年影像薈萃
- 腫瘤揭秘
- 帕金森病中西醫(yī)結(jié)合診療與康復(fù)
- 結(jié)直腸癌老年患者治療與康復(fù)
- 結(jié)核病診斷與防治技術(shù)
- 化妝品生產(chǎn)質(zhì)量管理規(guī)范240問
- 肝臟外科名家手術(shù)精粹
- 重癥肺病名醫(yī)學(xué)術(shù)經(jīng)驗(yàn)傳承與實(shí)踐