#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
}
}
}