| File: Interactivity\EventTrigger.cs | Web Access |
| Project: src\src\Controls\src\Core\Controls.Core.csproj (Microsoft.Maui.Controls) |
#nullable disable using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using Microsoft.Extensions.Logging; using Microsoft.Maui.Controls.Internals; namespace Microsoft.Maui.Controls { /// <include file="../../../docs/Microsoft.Maui.Controls/EventTrigger.xml" path="Type[@FullName='Microsoft.Maui.Controls.EventTrigger']/Docs/*" /> [ContentProperty("Actions")] public sealed class EventTrigger : TriggerBase { static readonly MethodInfo s_handlerinfo = typeof(EventTrigger).GetRuntimeMethods().Single(mi => mi.Name == "OnEventTriggered" && mi.IsPublic == false); readonly List<WeakReference<BindableObject>> _associatedObjects = new List<WeakReference<BindableObject>>(); EventInfo _eventinfo; string _eventname; Delegate _handlerdelegate; /// <include file="../../../docs/Microsoft.Maui.Controls/EventTrigger.xml" path="//Member[@MemberName='.ctor']/Docs/*" /> public EventTrigger() : base(typeof(BindableObject)) { Actions = new SealedList<TriggerAction>(); } /// <include file="../../../docs/Microsoft.Maui.Controls/EventTrigger.xml" path="//Member[@MemberName='Actions']/Docs/*" /> public IList<TriggerAction> Actions { get; } /// <include file="../../../docs/Microsoft.Maui.Controls/EventTrigger.xml" path="//Member[@MemberName='Event']/Docs/*" /> public string Event { get { return _eventname; } set { if (_eventname == value) return; if (IsSealed) throw new InvalidOperationException("Event cannot be changed once the Trigger has been applied"); OnPropertyChanging(); _eventname = value; OnPropertyChanged(); } } internal override void OnAttachedTo(BindableObject bindable) { base.OnAttachedTo(bindable); if (!string.IsNullOrEmpty(Event)) AttachHandlerTo(bindable); _associatedObjects.Add(new WeakReference<BindableObject>(bindable)); } internal override void OnDetachingFrom(BindableObject bindable) { _associatedObjects.RemoveAll(wr => { if (wr.TryGetTarget(out var target) && target == bindable) { DetachHandlerFrom(bindable); return true; } return false; }); base.OnDetachingFrom(bindable); } internal override void OnSeal() { base.OnSeal(); ((SealedList<TriggerAction>)Actions).IsReadOnly = true; } void AttachHandlerTo(BindableObject bindable) { try { _eventinfo = bindable.GetType().GetRuntimeEvent(Event); _handlerdelegate = ((EventHandler)OnEventTriggered).Method.CreateDelegate(_eventinfo.EventHandlerType, this); } catch (Exception) { Application.Current?.FindMauiContext()?.CreateLogger<EventTrigger>()?.LogWarning("Cannot attach EventTrigger to {Type}.{Event}. Check if the handler exists and if the signature is right.", bindable.GetType(), Event); } if (_eventinfo != null && _handlerdelegate != null) _eventinfo.AddEventHandler(bindable, _handlerdelegate); } void DetachHandlerFrom(BindableObject bindable) { if (_eventinfo != null && _handlerdelegate != null) _eventinfo.RemoveEventHandler(bindable, _handlerdelegate); } void OnEventTriggered(object sender, EventArgs e) { var bindable = (BindableObject)sender; foreach (TriggerAction action in Actions) action.DoInvoke(bindable); } } }