summaryrefslogtreecommitdiff
path: root/Xamarin.Forms.Core/Interactivity/EventTrigger.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Xamarin.Forms.Core/Interactivity/EventTrigger.cs')
-rw-r--r--Xamarin.Forms.Core/Interactivity/EventTrigger.cs91
1 files changed, 91 insertions, 0 deletions
diff --git a/Xamarin.Forms.Core/Interactivity/EventTrigger.cs b/Xamarin.Forms.Core/Interactivity/EventTrigger.cs
new file mode 100644
index 00000000..52e221a0
--- /dev/null
+++ b/Xamarin.Forms.Core/Interactivity/EventTrigger.cs
@@ -0,0 +1,91 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+
+namespace Xamarin.Forms
+{
+ [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<BindableObject> _associatedObjects = new List<BindableObject>();
+
+ EventInfo _eventinfo;
+
+ string _eventname;
+ Delegate _handlerdelegate;
+
+ public EventTrigger() : base(typeof(BindableObject))
+ {
+ Actions = new SealedList<TriggerAction>();
+ }
+
+ public IList<TriggerAction> Actions { get; }
+
+ 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(bindable);
+ }
+
+ internal override void OnDetachingFrom(BindableObject bindable)
+ {
+ _associatedObjects.Remove(bindable);
+ DetachHandlerFrom(bindable);
+ 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 = s_handlerinfo.CreateDelegate(_eventinfo.EventHandlerType, this);
+ }
+ catch (Exception)
+ {
+ Log.Warning("EventTrigger", "Can not attach EventTrigger to {0}.{1}. 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);
+ }
+
+ [Preserve]
+ void OnEventTriggered(object sender, EventArgs e)
+ {
+ var bindable = (BindableObject)sender;
+ foreach (TriggerAction action in Actions)
+ action.DoInvoke(bindable);
+ }
+ }
+} \ No newline at end of file