| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251 | namespace Caliburn.Micro {    using System;    using System.Collections.Generic;    using System.Threading.Tasks;#if WinRT    using System.Reflection;    using Windows.UI.Core;    using Windows.UI.Xaml;#else    using System.Windows;    using System.Windows.Threading;    using Caliburn.Micro.Core;#endif    /// <summary>    /// A <see cref="IPlatformProvider"/> implementation for the XAML platfrom.    /// </summary>    public class XamlPlatformProvider : IPlatformProvider {#if WinRT        private CoreDispatcher dispatcher;#else        private Dispatcher dispatcher;#endif        /// <summary>        /// Initializes a new instance of the <see cref="XamlPlatformProvider"/> class.        /// </summary>        public XamlPlatformProvider() {#if SILVERLIGHT            dispatcher = System.Windows.Deployment.Current.Dispatcher;#elif WinRT            dispatcher = Window.Current.Dispatcher;#else            dispatcher = Dispatcher.CurrentDispatcher;#endif        }        /// <summary>        /// Indicates whether or not the framework is in design-time mode.        /// </summary>        public bool InDesignMode {            get { return View.InDesignMode; }        }        private void ValidateDispatcher() {            if (dispatcher == null)                throw new InvalidOperationException("Not initialized with dispatcher.");        }        private bool CheckAccess() {#if WinRT            return dispatcher == null || Window.Current != null;#else            return dispatcher == null || dispatcher.CheckAccess();#endif        }        /// <summary>        /// Executes the action on the UI thread asynchronously.        /// </summary>        /// <param name="action">The action to execute.</param>        public void BeginOnUIThread(System.Action action) {            ValidateDispatcher();#if WinRT            var dummy = dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => action());#else            dispatcher.BeginInvoke(action);#endif        }        /// <summary>        /// Executes the action on the UI thread asynchronously.        /// </summary>        /// <param name="action">The action to execute.</param>        /// <returns></returns>        public Task OnUIThreadAsync(System.Action action) {            ValidateDispatcher();#if WinRT            return dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => action()).AsTask();#elif NET45            return dispatcher.InvokeAsync(action).Task;#else            var taskSource = new TaskCompletionSource<object>();            System.Action method = () => {                try {                    action();                    taskSource.SetResult(null);                }                catch(Exception ex) {                    taskSource.SetException(ex);                }            };            dispatcher.BeginInvoke(method);            return taskSource.Task;#endif        }        /// <summary>        /// Executes the action on the UI thread.        /// </summary>        /// <param name="action">The action to execute.</param>        /// <exception cref="System.NotImplementedException"></exception>        public void OnUIThread(System.Action action) {            if (CheckAccess())                action();            else {#if WinRT                dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => action()).AsTask().Wait();#elif NET                Exception exception = null;                System.Action method = () => {                    try {                        action();                    }                    catch(Exception ex) {                        exception = ex;                    }                };                dispatcher.Invoke(method);                if (exception != null)                    throw new System.Reflection.TargetInvocationException("An error occurred while dispatching a call to the UI Thread", exception);#else                var waitHandle = new System.Threading.ManualResetEvent(false);                Exception exception = null;                System.Action method = () => {                    try {                        action();                    }                    catch (Exception ex) {                        exception = ex;                    }                    waitHandle.Set();                };                dispatcher.BeginInvoke(method);                waitHandle.WaitOne();                if (exception != null)                    throw new System.Reflection.TargetInvocationException("An error occurred while dispatching a call to the UI Thread", exception);#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 object GetFirstNonGeneratedView(object view) {            return View.GetFirstNonGeneratedView(view);        }        private static readonly DependencyProperty PreviouslyAttachedProperty = DependencyProperty.RegisterAttached(            "PreviouslyAttached",            typeof (bool),            typeof (XamlPlatformProvider),            null            );        /// <summary>        /// Executes the handler the fist time the view is loaded.        /// </summary>        /// <param name="view">The view.</param>        /// <param name="handler">The handler.</param>        public void ExecuteOnFirstLoad(object view, Action<object> handler) {            var element = view as FrameworkElement;            if (element != null && !(bool) element.GetValue(PreviouslyAttachedProperty)) {                element.SetValue(PreviouslyAttachedProperty, true);                View.ExecuteOnLoad(element, (s, e) => handler(s));            }        }        /// <summary>        /// Executes the handler the next time the view's LayoutUpdated event fires.        /// </summary>        /// <param name="view">The view.</param>        /// <param name="handler">The handler.</param>        public void ExecuteOnLayoutUpdated(object view, Action<object> handler) {            var element = view as FrameworkElement;            if (element != null) {                View.ExecuteOnLayoutUpdated(element, (s, e) => handler(s));            }        }        /// <summary>        /// Get the close action for the specified view model.        /// </summary>        /// <param name="viewModel">The view model to close.</param>        /// <param name="views">The associated views.</param>        /// <param name="dialogResult">The dialog result.</param>        /// <returns>        /// An <see cref="Action" /> to close the view model.        /// </returns>        /// <exception cref="System.NotImplementedException"></exception>        public System.Action GetViewCloseAction(object viewModel, ICollection<object> views, bool? dialogResult) {            var child = viewModel as IChild;            if (child != null) {                var conductor = child.Parent as IConductor;                if (conductor != null) {                    return () => conductor.CloseItem(viewModel);                }            }            foreach (var contextualView in views) {                var viewType = contextualView.GetType();#if WinRT                var closeMethod = viewType.GetRuntimeMethod("Close", new Type[0]);#else                var closeMethod = viewType.GetMethod("Close");#endif                if (closeMethod != null)                    return () => {#if !SILVERLIGHT && !WinRT                        var isClosed = false;                        if (dialogResult != null) {                            var resultProperty = contextualView.GetType().GetProperty("DialogResult");                            if (resultProperty != null) {                                resultProperty.SetValue(contextualView, dialogResult, null);                                isClosed = true;                            }                        }                        if (!isClosed) {                            closeMethod.Invoke(contextualView, null);                        }#else                        closeMethod.Invoke(contextualView, null);#endif                    };#if WinRT                var isOpenProperty = viewType.GetRuntimeProperty("IsOpen");#else                var isOpenProperty = viewType.GetProperty("IsOpen");#endif                if (isOpenProperty != null) {                    return () => isOpenProperty.SetValue(contextualView, false, null);                }            }            return () => LogManager.GetLog(typeof(Screen)).Info("TryClose requires a parent IConductor or a view with a Close method or IsOpen property.");        }    }}
 |