Behavior(行为)

本文详细介绍了如何创建和使用Xamarin.Forms的行为,包括Behavior和EffectBehavior的实现。内容涵盖创建自定义行为、在XAML和C#中应用行为、使用Style绑定行为、在平台项目中实现Effect以及通过EffectBehavior添加特定于平台的效果。同时提供了示例代码展示如何在iOS和Android上运行。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

创建行为

  • 创建一个继承自Behavior或Behavoir的自定义类,其中T是被将附加该行为的控件类型。
  • 重写OnAttachedTo方法以执行所需业务逻辑。
  • 重写OnDetachingFrom方法以执行所需的清理。
    public class NumericValidationBehavior:Behavior<Entry>
    {
        protected override void OnAttachedTo(Entry bindable)
        {
            base.OnAttachedTo(bindable);
            bindable.TextChanged += OnEntryTextChanged;
        }
        protected override void OnDetachingFrom(Entry bindable)
        {
            base.OnDetachingFrom(bindable);
            bindable.TextChanged -= OnEntryTextChanged;
        }
        void OnEntryTextChanged(object sender,TextChangedEventArgs args)
        {
            double result;
            bool isValid = double.TryParse(args.NewTextValue, out result);
            (sender as Entry).TextColor = isValid ?Color.Default:Color.Red;
        }
    }

OnAttachedTo方法在行为附加到控件后立即触发。
OnDetachingFrom方法在从控件中删除行为时触发。
使用Xamarin.Form行为
xaml:

        <Entry Placeholder="Enter a System.Double">
            <Entry.Behaviors>
                <behaviorsample:NumericValidationBehavior/>
            </Entry.Behaviors>
        </Entry>

C#:

var entry = new Entry { Placeholder = "Enter a System.Double" };
entry.Behaviors.Add (new NumericValidationBehavior ());

使用Sytle来应用行为

  1. 将附加属性添加到自定义的行为类中,以控制从控件中添加和删除行为。确保附加属性注册propertyChanged委托,该委托将在属性值更改时执行。
  2. 为附加属性创建static的getter和setter。
  3. 在propertyChanged委托中实现逻辑以添加和删除行为。
        #region 使用Style来定义Behavior,通过附加属性来实现
        public static readonly BindableProperty AttachBehaviorProperty = BindableProperty.CreateAttached("AttachBehavior",typeof(bool),typeof(NumericValidationBehavior),false,propertyChanged:OnAttachBehaviorChanged);
        public static bool GetAttachBehavior(BindableObject view)
            => (bool)view.GetValue(AttachBehaviorProperty);
        public static void SetAttachBehavior(BindableObject view,bool value)
            => view.SetValue(AttachBehaviorProperty,value);
        static void OnAttachBehaviorChanged(BindableObject view,object oldValue,object newValue)
        {
            var entry = view as Entry;
            if (entry is null)
            {
                return;
            }
            bool attachBehavior = (bool)newValue;
            if (attachBehavior)
            {
                entry.Behaviors.Add(new NumericValidationBehavior());
            }
            else
            {
                var toRemove = entry.Behaviors.FirstOrDefault(b => b is NumericValidationBehavior);
                if (toRemove != null)
                {
                    entry.Behaviors.Remove(toRemove);
                }
            }
        }
        #endregion

应用行为

    <ContentPage.Resources>
        <Style x:Key="NumericValidationStyle" TargetType="Entry">
            <Style.Setters>
                <Setter Property="behaviorsample:NumericValidationBehavior.AttachBehavior" Value="True"/>
            </Style.Setters>
        </Style>
    </ContentPage.Resources>
        <Entry Placeholder="Enter a System.Double"
               Style="{StaticResource NumericValidationStyle}"/>

官方Doc

EffectBehavior

使用Behavior可以向控件添加特定于平台的效果、从隐藏代码中省去冗余重复的效果处理代码。

概述

EffectBehavior自定义类是可重用的Xmarin.Forms自定义行为,当行为附加到控件时,它会将Effect实例添加到控件,当行为与控件分离时,它将删除Effect实例。
必须设置一下行为属性才能使用该行为:

  • Group - 平台项目的自定义效果类特性ResolutionGroupName的属性值。
  • Name - 平台项目的自定义效果类特性ExportEffect的属性值。

创建行为

EffectBehavior自定义类派生自Behavior类,其中T是View。这意味着EffectBehavior自定义类可以附加到任何Xamarin.Forms控件。

实现 BindableProperty

在共享项目中,创建EffectBehavior自定义类,该自定义类定义了两个 BindableProperty 实例,当行为附加到控件时,这些实例用于向控件添加Effect。

    public class EffectBehavior:Behavior<View>
    {
        public static readonly BindableProperty GroupProperty =
            BindableProperty.Create("Group",typeof(string),typeof(EffectBehavior),null);
        public static readonly BindableProperty NameProperty =
            BindableProperty.Create("Name",typeof(string),typeof(EffectBehavior),null);
        public string Group
        {
            get => GetValue(GroupProperty) as string;
            set => SetValue(GroupProperty,value);
        }
        public string Name
        {
            get => GetValue(NameProperty) as string;
            set => SetValue(NameProperty,value);
        }
    }

当使用EffectBehavior时,应将Group属性设置为特定于平台效果类的ResolutionGroupName特性的值。此外,应将Name属性设置为特定于平台效果类的ExportEffect特性的值。

重写OnAttachTo和OnDetachingFrom方法

        protected override void OnAttachedTo(BindableObject bindable)
        {
            base.OnAttachedTo(bindable);
            AddEffect(bindable as View);
        }
        protected override void OnDetachingFrom(BindableObject bindable)
        {
            base.OnDetachingFrom(bindable);
            RemoveEffect(bindable as View);
        }

添加和删除行为功能

当行为附加到控件时,将Group和Name属性中定义的Effect添加到控件,并在行为与控件分离时删除Effefct。

        Effect GetEffect()
        {
            if (!string.IsNullOrWhiteSpace(Group)&&!string.IsNullOrWhiteSpace(Name))
            {
                return Effect.Resolve($"{Group}.{Name}");
            }
            return null;
        }
        void AddEffect(View view)
        {
            var effect = GetEffect();
            if (effect != null)
            {
                view.Effects.Add(effect);
            }
        }
        void RemoveEffect(View view)
        {
            var efffect = GetEffect();
            if (efffect !=null)
            {
                view.Effects.Remove(GetEffect());
            }
        }

GetEffect方法使用Effect.Resolve方法检索Effect。通过串联Group和Name属性值来从平台项目中定位检索该效果。如果平台项目不提供此效果,则Effect.Resolve方法将返回 NullEffect 实例。

在平台项目中各自实现效果类

iOS

using System;
using System.Diagnostics;
using CoreGraphics;
using EffectBehaviorSample.iOS;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;

[assembly:ResolutionGroupName("Xamarin")]
[assembly:ExportEffect(typeof(LabelShadowEffect),"LabelShadowEffect")]
namespace EffectBehaviorSample.iOS
{
    public class LabelShadowEffect:PlatformEffect
    {
        public LabelShadowEffect()
        {
        }

        protected override void OnAttached()
        {
            try
            {
                Control.Layer.CornerRadius = 5;
                Control.Layer.ShadowColor = Color.Black.ToCGColor();
                Control.Layer.ShadowOffset = new CGSize(5,5);
                Control.Layer.ShadowOpacity = 1.0f;
            }
            catch (Exception ex)
            {
                Debug.WriteLine("Cannot set property on attached control:",ex.Message);
            }
        }

        protected override void OnDetached()
        {
            throw new NotImplementedException();
        }
    }
}

Droid

using System;
using System.Diagnostics;
using EffectBehaviorSample.Droid;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;

[assembly:ResolutionGroupName("Xamarin")]
[assembly:ExportEffect(typeof(LabelShadowEffect),"LabelShadowEffect")]
namespace EffectBehaviorSample.Droid
{
    public class LabelShadowEffect:PlatformEffect
    {
        public LabelShadowEffect()
        {
        }

        protected override void OnAttached()
        {
            try
            {
                var control = Control as Android.Widget.TextView;
                float radius = 5;
                float distanceX = 5;
                float distanceY = 10;
                Android.Graphics.Color color = Color.IndianRed.ToAndroid();
                control.SetShadowLayer(radius,distanceX,distanceY,color);
            }
            catch (Exception ex)
            {
                Debug.WriteLine("Cannot set property on attached control. Error: ",ex.Message);
            }
        }

        protected override void OnDetached()
        {
            throw new NotImplementedException();
        }
    }
}

对于此示例,共享项目EffectBehavior的Group属性应为"Xamarin",Name属性应为"LabelShadowEffect",即可检索到该特定于平台的效果。

使用Behavior

EffectBehavior类可以附加到控件的Behaviors集合。

    <StackLayout Margin="0,30,0,0"
                 HorizontalOptions="Center" VerticalOptions="Center">
        <Label Text="Label Shadow Effect">
            <Label.Behaviors>
                <effectbehaviorsample:EffectBehavior Group="Xamarin"
                                                     Name="LabelShadowEffect"/>
            </Label.Behaviors>
        </Label>
    </StackLayout>

等到的C#

var label = new Label {
  Text = "Label Shadow Effect",
  ...
};
label.Behaviors.Add (new EffectBehavior {
  Group = "Xamarin",
  Name = "LabelShadowEffect"
});

行为的Group和Name属性被设置为每个平台项目的效果类的ResolutionGroupName和ExportEffect特性的值。

运行示例

iOS
在这里插入图片描述
Droid
在这里插入图片描述
==官方Doc==

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值