#if XFORMS namespace Caliburn.Micro.Core.Xamarin.Forms #else namespace Caliburn.Micro #endif { #if WinRT using System.Linq; using Windows.UI.Xaml; using System.Reflection; #elif XFORMS using UIElement = global::Xamarin.Forms.Element; using FrameworkElement = global::Xamarin.Forms.VisualElement; using DependencyProperty = global::Xamarin.Forms.BindableProperty; using DependencyObject = global::Xamarin.Forms.BindableObject; #else using Caliburn.Micro.Core; using System.Windows; #endif /// /// A host for action related attached properties. /// public static class Action { static readonly ILog Log = LogManager.GetLog(typeof(Action)); /// /// A property definition representing the target of an . The DataContext of the element will be set to this instance. /// public static readonly DependencyProperty TargetProperty = DependencyPropertyHelper.RegisterAttached( "Target", typeof(object), typeof(Action), null, OnTargetChanged ); /// /// A property definition representing the target of an . The DataContext of the element is not set to this instance. /// public static readonly DependencyProperty TargetWithoutContextProperty = DependencyPropertyHelper.RegisterAttached( "TargetWithoutContext", typeof(object), typeof(Action), null, OnTargetWithoutContextChanged ); /// /// Sets the target of the . /// /// The element to attach the target to. /// The target for instances of . public static void SetTarget(DependencyObject d, object target) { d.SetValue(TargetProperty, target); } /// /// Gets the target for instances of . /// /// The element to which the target is attached. /// The target for instances of public static object GetTarget(DependencyObject d) { return d.GetValue(TargetProperty); } /// /// Sets the target of the . /// /// The element to attach the target to. /// The target for instances of . /// /// The DataContext will not be set. /// public static void SetTargetWithoutContext(DependencyObject d, object target) { d.SetValue(TargetWithoutContextProperty, target); } /// /// Gets the target for instances of . /// /// The element to which the target is attached. /// The target for instances of public static object GetTargetWithoutContext(DependencyObject d) { return d.GetValue(TargetWithoutContextProperty); } /// /// Checks if the -Target was set. /// /// DependencyObject to check /// True if Target or TargetWithoutContext was set on public static bool HasTargetSet(DependencyObject element) { if (GetTarget(element) != null || GetTargetWithoutContext(element) != null) return true; #if XFORMS return false; #else var frameworkElement = element as FrameworkElement; if (frameworkElement == null) return false; return ConventionManager.HasBinding(frameworkElement, TargetProperty) || ConventionManager.HasBinding(frameworkElement, TargetWithoutContextProperty); #endif } #if !XFORMS /// /// Uses the action pipeline to invoke the method. /// /// The object instance to invoke the method on. /// The name of the method to invoke. /// The view. /// The source of the invocation. /// The event args. /// The method parameters. public static void Invoke(object target, string methodName, DependencyObject view = null, FrameworkElement source = null, object eventArgs = null, object[] parameters = null) { var message = new ActionMessage {MethodName = methodName}; var context = new ActionExecutionContext { Target = target, #if WinRT Method = target.GetType().GetRuntimeMethods().Single(m => m.Name == methodName), #else Method = target.GetType().GetMethod(methodName), #endif Message = message, View = view, Source = source, EventArgs = eventArgs }; if (parameters != null) { parameters.Apply(x => context.Message.Parameters.Add(x as Parameter ?? new Parameter { Value = x })); } ActionMessage.InvokeAction(context); // This is a bit of hack but keeps message being garbage collected Log.Info("Invoking action {0} on {1}.", message.MethodName, target); } #endif static void OnTargetWithoutContextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { SetTargetCore(e, d, false); } static void OnTargetChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { SetTargetCore(e, d, true); } static void SetTargetCore(DependencyPropertyChangedEventArgs e, DependencyObject d, bool setContext) { if (e.NewValue == e.OldValue || (Execute.InDesignMode && e.NewValue is string)) { return; } var target = e.NewValue; var containerKey = e.NewValue as string; if (containerKey != null) { target = IoC.GetInstance(null, containerKey); } #if XFORMS Log.Info("Attaching message handler {0} to {1}.", target, d); Message.SetHandler(d, target); if (setContext && d is FrameworkElement) { Log.Info("Setting DC of {0} to {1}.", d, target); ((FrameworkElement)d).BindingContext = target; } #else if (setContext && d is FrameworkElement) { Log.Info("Setting DC of {0} to {1}.", d, target); ((FrameworkElement)d).DataContext = target; } Log.Info("Attaching message handler {0} to {1}.", target, d); Message.SetHandler(d, target); #endif } } }