| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443 | #if XFORMSnamespace Caliburn.Micro.Core.Xamarin.Forms#elsenamespace Caliburn.Micro#endif {    using System;    using System.Linq;#if WinRT    using System.Reflection;    using Windows.ApplicationModel;    using Windows.UI.Xaml;    using Windows.UI.Xaml.Controls;    using Windows.UI.Xaml.Markup;    using Windows.UI.Xaml.Media;#elif XFORMS    using System.Reflection;    using global::Xamarin.Forms;    using UIElement = global::Xamarin.Forms.Element;    using FrameworkElement = global::Xamarin.Forms.VisualElement;    using DependencyProperty = global::Xamarin.Forms.BindableProperty;    using DependencyObject = global::Xamarin.Forms.BindableObject;    using ContentControl = global::Xamarin.Forms.ContentView;#else    using System.ComponentModel;    using System.Windows;    using System.Windows.Controls;    using System.Windows.Markup;    using Caliburn.Micro.Core;#endif    /// <summary>    /// Hosts attached properties related to view models.    /// </summary>    public static class View {        static readonly ILog Log = LogManager.GetLog(typeof(View));#if WinRT || XFORMS        const string DefaultContentPropertyName = "Content";#else        static readonly ContentPropertyAttribute DefaultContentProperty = new ContentPropertyAttribute("Content");#endif        /// <summary>        /// A dependency property which allows the framework to track whether a certain element has already been loaded in certain scenarios.        /// </summary>        public static readonly DependencyProperty IsLoadedProperty =            DependencyPropertyHelper.RegisterAttached(                "IsLoaded",                typeof(bool),                typeof(View),                false                );        /// <summary>        /// A dependency property which marks an element as a name scope root.        /// </summary>        public static readonly DependencyProperty IsScopeRootProperty =            DependencyPropertyHelper.RegisterAttached(                "IsScopeRoot",                typeof(bool),                typeof(View),                false                );        /// <summary>        /// A dependency property which allows the override of convention application behavior.        /// </summary>        public static readonly DependencyProperty ApplyConventionsProperty =            DependencyPropertyHelper.RegisterAttached(                "ApplyConventions",                typeof(bool?),                typeof(View)                );        /// <summary>        /// A dependency property for assigning a context to a particular portion of the UI.        /// </summary>        public static readonly DependencyProperty ContextProperty =            DependencyPropertyHelper.RegisterAttached(                "Context",                typeof(object),                typeof(View),                null,                 OnContextChanged                );        /// <summary>        /// A dependency property for attaching a model to the UI.        /// </summary>        public static DependencyProperty ModelProperty =            DependencyPropertyHelper.RegisterAttached(                "Model",                typeof(object),                typeof(View),                null,                 OnModelChanged                );        /// <summary>        /// Used by the framework to indicate that this element was generated.        /// </summary>        public static readonly DependencyProperty IsGeneratedProperty =            DependencyPropertyHelper.RegisterAttached(                "IsGenerated",                typeof(bool),                typeof(View),                false                );        /// <summary>        /// Executes the handler immediately if the element is loaded, otherwise wires it to the Loaded event.        /// </summary>        /// <param name="element">The element.</param>        /// <param name="handler">The handler.</param>        /// <returns>true if the handler was executed immediately; false otherwise</returns>        public static bool ExecuteOnLoad(FrameworkElement element, RoutedEventHandler handler) {#if XFORMS            handler(element, new RoutedEventArgs());            return true;#else#if SILVERLIGHT            if ((bool)element.GetValue(IsLoadedProperty)) {#elif WinRT            if (IsElementLoaded(element)) {#else            if(element.IsLoaded) {#endif                handler(element, new RoutedEventArgs());                return true;            }            RoutedEventHandler loaded = null;            loaded = (s, e) => {                element.Loaded -= loaded;#if SILVERLIGHT                element.SetValue(IsLoadedProperty, true);#endif                handler(s, e);            };            element.Loaded += loaded;            return false;#endif        }        /// <summary>        /// Executes the handler when the element is unloaded.        /// </summary>        /// <param name="element">The element.</param>        /// <param name="handler">The handler.</param>        public static void ExecuteOnUnload(FrameworkElement element, RoutedEventHandler handler) {#if !XFORMS            RoutedEventHandler unloaded = null;            unloaded = (s, e) => {                element.Unloaded -= unloaded;                handler(s, e);            };            element.Unloaded += unloaded;#endif        }#if WinRT        /// <summary>        /// Determines whether the specified <paramref name="element"/> is loaded.        /// </summary>        /// <param name="element">The element.</param>        /// <returns>true if the element is loaded; otherwise, false.        /// </returns>        public static bool IsElementLoaded(FrameworkElement element) {            try            {                if ((element.Parent ?? VisualTreeHelper.GetParent(element)) != null)                {                    return true;                }                var rootVisual = Window.Current.Content;                if (rootVisual != null)                {                    return element == rootVisual;                }                return false;            }            catch            {                return false;            }        }#endif        /// <summary>        /// Executes the handler the next time the elements's LayoutUpdated event fires.        /// </summary>        /// <param name="element">The element.</param>        /// <param name="handler">The handler.</param>#if WinRT        public static void ExecuteOnLayoutUpdated(FrameworkElement element, EventHandler<object> handler) {            EventHandler<object> onLayoutUpdate = null;#else        public static void ExecuteOnLayoutUpdated(FrameworkElement element, EventHandler handler) {            EventHandler onLayoutUpdate = null;#endif#if !XFORMS            onLayoutUpdate = (s, e) => {                element.LayoutUpdated -= onLayoutUpdate;                handler(element, e);            };            element.LayoutUpdated += onLayoutUpdate;#endif        }        /// <summary>        /// Used to retrieve the root, non-framework-created view.        /// </summary>        /// <param name="view">The view to search.</param>        /// <returns>The root element that was not created by the framework.</returns>        /// <remarks>In certain instances the services create UI elements.        /// For example, if you ask the window manager to show a UserControl as a dialog, it creates a window to host the UserControl in.        /// The WindowManager marks that element as a framework-created element so that it can determine what it created vs. what was intended by the developer.        /// Calling GetFirstNonGeneratedView allows the framework to discover what the original element was.         /// </remarks>        public static Func<object, object> GetFirstNonGeneratedView = view => {            var dependencyObject = view as DependencyObject;            if (dependencyObject == null) {                return view;            }            if ((bool)dependencyObject.GetValue(IsGeneratedProperty)) {                if (dependencyObject is ContentControl) {                    return ((ContentControl)dependencyObject).Content;                }#if WinRT || XFORMS                var type = dependencyObject.GetType();                var contentPropertyName = GetContentPropertyName(type);                return type.GetRuntimeProperty(contentPropertyName)                    .GetValue(dependencyObject, null);#else                var type = dependencyObject.GetType();                var contentProperty = type.GetAttributes<ContentPropertyAttribute>(true)                                          .FirstOrDefault() ?? DefaultContentProperty;                return type.GetProperty(contentProperty.Name)                    .GetValue(dependencyObject, null);#endif            }            return dependencyObject;        };        /// <summary>        /// Gets the convention application behavior.        /// </summary>        /// <param name="d">The element the property is attached to.</param>        /// <returns>Whether or not to apply conventions.</returns>        public static bool? GetApplyConventions(DependencyObject d) {            return (bool?)d.GetValue(ApplyConventionsProperty);        }        /// <summary>        /// Sets the convention application behavior.        /// </summary>        /// <param name="d">The element to attach the property to.</param>        /// <param name="value">Whether or not to apply conventions.</param>        public static void SetApplyConventions(DependencyObject d, bool? value) {            d.SetValue(ApplyConventionsProperty, value);        }        /// <summary>        /// Sets the model.        /// </summary>        /// <param name="d">The element to attach the model to.</param>        /// <param name="value">The model.</param>        public static void SetModel(DependencyObject d, object value) {            d.SetValue(ModelProperty, value);        }        /// <summary>        /// Gets the model.        /// </summary>        /// <param name="d">The element the model is attached to.</param>        /// <returns>The model.</returns>        public static object GetModel(DependencyObject d) {            return d.GetValue(ModelProperty);        }        /// <summary>        /// Gets the context.        /// </summary>        /// <param name="d">The element the context is attached to.</param>        /// <returns>The context.</returns>        public static object GetContext(DependencyObject d) {            return d.GetValue(ContextProperty);        }        /// <summary>        /// Sets the context.        /// </summary>        /// <param name="d">The element to attach the context to.</param>        /// <param name="value">The context.</param>        public static void SetContext(DependencyObject d, object value) {            d.SetValue(ContextProperty, value);        }        static void OnModelChanged(DependencyObject targetLocation, DependencyPropertyChangedEventArgs args) {            if (args.OldValue == args.NewValue) {                return;            }            if (args.NewValue != null) {                var context = GetContext(targetLocation);                                var view = ViewLocator.LocateForModel(args.NewValue, targetLocation, context);                // Trialing binding before setting content in Xamarin Forms#if XFORMS                ViewModelBinder.Bind(args.NewValue, view, context);#endif                if (!SetContentProperty(targetLocation, view)) {                    Log.Warn("SetContentProperty failed for ViewLocator.LocateForModel, falling back to LocateForModelType");                    view = ViewLocator.LocateForModelType(args.NewValue.GetType(), targetLocation, context);                    SetContentProperty(targetLocation, view);                }#if !XFORMS                ViewModelBinder.Bind(args.NewValue, view, context);#endif            }            else {                SetContentProperty(targetLocation, args.NewValue);            }        }        static void OnContextChanged(DependencyObject targetLocation, DependencyPropertyChangedEventArgs e) {            if (e.OldValue == e.NewValue) {                return;            }            var model = GetModel(targetLocation);            if (model == null) {                return;            }            var view = ViewLocator.LocateForModel(model, targetLocation, e.NewValue);            if (!SetContentProperty(targetLocation, view)) {                Log.Warn("SetContentProperty failed for ViewLocator.LocateForModel, falling back to LocateForModelType");                view = ViewLocator.LocateForModelType(model.GetType(), targetLocation, e.NewValue);                SetContentProperty(targetLocation, view);            }            ViewModelBinder.Bind(model, view, e.NewValue);        }        static bool SetContentProperty(object targetLocation, object view) {            var fe = view as FrameworkElement;            if (fe != null && fe.Parent != null) {                SetContentPropertyCore(fe.Parent, null);            }            return SetContentPropertyCore(targetLocation, view);        }#if WinRT || XFORMS        static bool SetContentPropertyCore(object targetLocation, object view) {            try {                var type = targetLocation.GetType();                var contentPropertyName = GetContentPropertyName(type);                type.GetRuntimeProperty(contentPropertyName)                    .SetValue(targetLocation, view, null);                return true;            }            catch (Exception e) {                Log.Error(e);                return false;            }        }        private static string GetContentPropertyName(Type type) {            var typeInfo = type.GetTypeInfo();            var contentProperty = typeInfo.GetCustomAttribute<ContentPropertyAttribute>();                        return contentProperty?.Name ?? DefaultContentPropertyName;        }#else        static bool SetContentPropertyCore(object targetLocation, object view) {            try {                var type = targetLocation.GetType();                var contentProperty = type.GetAttributes<ContentPropertyAttribute>(true)                                          .FirstOrDefault() ?? DefaultContentProperty;                type.GetProperty(contentProperty.Name ?? DefaultContentProperty.Name)                    .SetValue(targetLocation, view, null);                return true;            }            catch(Exception e) {                Log.Error(e);                return false;            }        }#endif        private static bool? inDesignMode;        /// <summary>        /// Gets a value that indicates whether the process is running in design mode.        /// </summary>        public static bool InDesignMode        {            get            {                if (inDesignMode == null)                {#if XFORMS                    inDesignMode = false;#elif WinRT                    inDesignMode = DesignMode.DesignModeEnabled;#elif SILVERLIGHT                    inDesignMode = DesignerProperties.IsInDesignTool;#else                    var descriptor = DependencyPropertyDescriptor.FromProperty(DesignerProperties.IsInDesignModeProperty, typeof(FrameworkElement));                    inDesignMode = (bool)descriptor.Metadata.DefaultValue;#endif                }                return inDesignMode.GetValueOrDefault(false);            }        }    }}
 |