Browse Source

Added Raised observable to RoutedEvent.

Similar to PerspexProperty.Changed observable. Make AddClassHandler
methods use this.
pull/422/head
Steven Kirk 10 years ago
parent
commit
be8079137d
  1. 2
      src/Perspex.Interactivity/Interactive.cs
  2. 70
      src/Perspex.Interactivity/RoutedEvent.cs

2
src/Perspex.Interactivity/Interactive.cs

@ -175,7 +175,7 @@ namespace Perspex.Interactivity
{ {
Contract.Requires<ArgumentNullException>(e != null); Contract.Requires<ArgumentNullException>(e != null);
e.RoutedEvent.InvokeClassHandlers(this, e); e.RoutedEvent.InvokeRaised(this, e);
List<EventSubscription> subscriptions; List<EventSubscription> subscriptions;

70
src/Perspex.Interactivity/RoutedEvent.cs

@ -2,8 +2,7 @@
// Licensed under the MIT license. See licence.md file in the project root for full license information. // Licensed under the MIT license. See licence.md file in the project root for full license information.
using System; using System;
using System.Collections.Generic; using System.Reactive.Subjects;
using System.Linq.Expressions;
using System.Reflection; using System.Reflection;
using System.Runtime.ExceptionServices; using System.Runtime.ExceptionServices;
@ -19,7 +18,7 @@ namespace Perspex.Interactivity
public class RoutedEvent public class RoutedEvent
{ {
private readonly List<ClassEventSubscription> _subscriptions = new List<ClassEventSubscription>(); private Subject<Tuple<object, RoutedEventArgs>> _raised = new Subject<Tuple<object, RoutedEventArgs>>();
public RoutedEvent( public RoutedEvent(
string name, string name,
@ -62,6 +61,8 @@ namespace Perspex.Interactivity
private set; private set;
} }
public IObservable<Tuple<object, RoutedEventArgs>> Raised => _raised;
public static RoutedEvent<TEventArgs> Register<TOwner, TEventArgs>( public static RoutedEvent<TEventArgs> Register<TOwner, TEventArgs>(
string name, string name,
RoutingStrategies routingStrategy) RoutingStrategies routingStrategy)
@ -83,27 +84,24 @@ namespace Perspex.Interactivity
return new RoutedEvent<TEventArgs>(name, routingStrategy, ownerType); return new RoutedEvent<TEventArgs>(name, routingStrategy, ownerType);
} }
public void AddClassHandler(Type type, EventHandler<RoutedEventArgs> handler, RoutingStrategies routes) public IDisposable AddClassHandler(
Type targetType,
EventHandler<RoutedEventArgs> handler,
RoutingStrategies routes = RoutingStrategies.Direct | RoutingStrategies.Bubble,
bool handledEventsToo = false)
{ {
_subscriptions.Add(new ClassEventSubscription return Raised.Subscribe(args =>
{ {
TargetType = type, var sender = args.Item1;
Handler = handler, var e = args.Item2;
Routes = routes,
});
}
internal void InvokeClassHandlers(object sender, RoutedEventArgs e) if (targetType.GetTypeInfo().IsAssignableFrom(sender.GetType().GetTypeInfo()) &&
{ ((e.Route == RoutingStrategies.Direct) || (e.Route & routes) != 0) &&
foreach (var sub in _subscriptions) (!e.Handled || handledEventsToo))
{
if (sub.TargetType.GetTypeInfo().IsAssignableFrom(sender.GetType().GetTypeInfo()) &&
((e.Route == RoutingStrategies.Direct) || (e.Route & sub.Routes) != 0) &&
(!e.Handled || sub.AlsoIfHandled))
{ {
try try
{ {
sub.Handler.DynamicInvoke(sender, e); handler.DynamicInvoke(sender, e);
} }
catch (TargetInvocationException ex) catch (TargetInvocationException ex)
{ {
@ -111,12 +109,12 @@ namespace Perspex.Interactivity
ExceptionDispatchInfo.Capture(ex.InnerException).Throw(); ExceptionDispatchInfo.Capture(ex.InnerException).Throw();
} }
} }
} });
} }
private class ClassEventSubscription : EventSubscription internal void InvokeRaised(object sender, RoutedEventArgs e)
{ {
public Type TargetType { get; set; } _raised.OnNext(Tuple.Create(sender, e));
} }
} }
@ -130,26 +128,24 @@ namespace Perspex.Interactivity
Contract.Requires<ArgumentNullException>(ownerType != null); Contract.Requires<ArgumentNullException>(ownerType != null);
} }
public void AddClassHandler<TTarget>( public IDisposable AddClassHandler<TTarget>(
Func<TTarget, Action<TEventArgs>> handler, Func<TTarget, Action<TEventArgs>> handler,
RoutingStrategies routes = RoutingStrategies.Direct | RoutingStrategies.Bubble) RoutingStrategies routes = RoutingStrategies.Direct | RoutingStrategies.Bubble,
where TTarget : class bool handledEventsToo = false)
where TTarget : class, IInteractive
{ {
AddClassHandler(typeof(TTarget), (s, e) => ClassHandlerAdapter<TTarget>(s, e, handler), routes); EventHandler<RoutedEventArgs> adapter = (sender, e) =>
} {
var target = sender as TTarget;
var args = e as TEventArgs;
private static void ClassHandlerAdapter<TTarget>( if (target != null && args != null)
object sender, {
RoutedEventArgs e, handler(target)(args);
Func<TTarget, Action<TEventArgs>> handler) where TTarget : class }
{ };
var target = sender as TTarget;
var args = e as TEventArgs;
if (target != null && args != null) return AddClassHandler(typeof(TTarget), adapter, routes, handledEventsToo);
{
handler(target)(args);
}
} }
} }
} }

Loading…
Cancel
Save