From d4c56f3a1f41e89fbbf171e8ba9cd56f7ba8386c Mon Sep 17 00:00:00 2001 From: Marcel Juen Date: Fri, 9 Aug 2019 17:54:40 +0200 Subject: [PATCH 1/6] Added .NET Core 3.0 target to Caliburn.Micro.Platform and renamed shared folder --- .../Caliburn.Micro.Platform.Tests.csproj | 4 +- src/Caliburn.Micro.Platform/ActionMessage.cs | 2 +- src/Caliburn.Micro.Platform/Bind.cs | 2 +- src/Caliburn.Micro.Platform/BindingScope.cs | 2 +- .../Caliburn.Micro.Platform.csproj | 12 +- .../ConventionManager.cs | 2 +- .../Platforms/net46-netcore/AssemblyInfo.cs | 8 + .../net46-netcore/AttachedCollection.cs | 85 ++++ .../Platforms/net46-netcore/Bootstrapper.cs | 222 +++++++++ .../net46-netcore/INavigationService.cs | 378 +++++++++++++++ .../net46-netcore/NavigationExtensions.cs | 21 + .../net46-netcore/NavigationHelper.cs | 55 +++ .../Platforms/net46-netcore/Parameter.cs | 88 ++++ .../Platforms/net46-netcore/WindowManager.cs | 431 ++++++++++++++++++ src/global.json | 2 +- 15 files changed, 1303 insertions(+), 11 deletions(-) create mode 100644 src/Caliburn.Micro.Platform/Platforms/net46-netcore/AssemblyInfo.cs create mode 100644 src/Caliburn.Micro.Platform/Platforms/net46-netcore/AttachedCollection.cs create mode 100644 src/Caliburn.Micro.Platform/Platforms/net46-netcore/Bootstrapper.cs create mode 100644 src/Caliburn.Micro.Platform/Platforms/net46-netcore/INavigationService.cs create mode 100644 src/Caliburn.Micro.Platform/Platforms/net46-netcore/NavigationExtensions.cs create mode 100644 src/Caliburn.Micro.Platform/Platforms/net46-netcore/NavigationHelper.cs create mode 100644 src/Caliburn.Micro.Platform/Platforms/net46-netcore/Parameter.cs create mode 100644 src/Caliburn.Micro.Platform/Platforms/net46-netcore/WindowManager.cs diff --git a/src/Caliburn.Micro.Platform.Tests/Caliburn.Micro.Platform.Tests.csproj b/src/Caliburn.Micro.Platform.Tests/Caliburn.Micro.Platform.Tests.csproj index 9a55b6cc..365181c4 100644 --- a/src/Caliburn.Micro.Platform.Tests/Caliburn.Micro.Platform.Tests.csproj +++ b/src/Caliburn.Micro.Platform.Tests/Caliburn.Micro.Platform.Tests.csproj @@ -7,6 +7,7 @@ + @@ -21,9 +22,6 @@ - - C:\Program Files (x86)\Microsoft SDKs\Expression\Blend\.NETFramework\v4.5\Libraries\System.Windows.Interactivity.dll - diff --git a/src/Caliburn.Micro.Platform/ActionMessage.cs b/src/Caliburn.Micro.Platform/ActionMessage.cs index 82ee992b..2dbf0131 100644 --- a/src/Caliburn.Micro.Platform/ActionMessage.cs +++ b/src/Caliburn.Micro.Platform/ActionMessage.cs @@ -191,7 +191,7 @@ void ElementLoaded(object sender, RoutedEventArgs e) { } else currentElement = context.View; -#if NET +#if NET || NETCOREAPP var binding = new Binding { Path = new PropertyPath(Message.HandlerProperty), Source = currentElement diff --git a/src/Caliburn.Micro.Platform/Bind.cs b/src/Caliburn.Micro.Platform/Bind.cs index 1ccd58ac..03c87b31 100644 --- a/src/Caliburn.Micro.Platform/Bind.cs +++ b/src/Caliburn.Micro.Platform/Bind.cs @@ -154,7 +154,7 @@ static void ModelWithoutContextChanged(DependencyObject d, DependencyPropertyCha /// /// The ui to apply conventions to. /// Whether or not conventions are applied. -#if NET +#if NET || NETCOREAPP [AttachedPropertyBrowsableForTypeAttribute(typeof(DependencyObject))] #endif public static bool GetAtDesignTime(DependencyObject dependencyObject) { diff --git a/src/Caliburn.Micro.Platform/BindingScope.cs b/src/Caliburn.Micro.Platform/BindingScope.cs index 3fa98225..34d27146 100644 --- a/src/Caliburn.Micro.Platform/BindingScope.cs +++ b/src/Caliburn.Micro.Platform/BindingScope.cs @@ -169,7 +169,7 @@ public static bool RemoveChildResolver(ChildResolver resolver) { continue; } -#if NET +#if NET || NETCOREAPP var childCount = (current is Visual || current is Visual3D) ? VisualTreeHelper.GetChildrenCount(current) : 0; #else diff --git a/src/Caliburn.Micro.Platform/Caliburn.Micro.Platform.csproj b/src/Caliburn.Micro.Platform/Caliburn.Micro.Platform.csproj index 13d5cf33..a1280721 100644 --- a/src/Caliburn.Micro.Platform/Caliburn.Micro.Platform.csproj +++ b/src/Caliburn.Micro.Platform/Caliburn.Micro.Platform.csproj @@ -1,7 +1,7 @@  - net45;uap10.0.16299;Xamarin.iOS10;MonoAndroid80;netstandard2.0 + net45;uap10.0.16299;Xamarin.iOS10;MonoAndroid80;netstandard2.0;netcoreapp3.0 Caliburn.Micro Caliburn.Micro Caliburn.Micro @@ -28,7 +28,13 @@ - + + + + + + + @@ -74,7 +80,7 @@ - + diff --git a/src/Caliburn.Micro.Platform/ConventionManager.cs b/src/Caliburn.Micro.Platform/ConventionManager.cs index fdcb534f..0d01062b 100644 --- a/src/Caliburn.Micro.Platform/ConventionManager.cs +++ b/src/Caliburn.Micro.Platform/ConventionManager.cs @@ -363,7 +363,7 @@ public static ElementConvention GetElementConvention(Type elementType) { /// Determines whether a particular dependency property already has a binding on the provided element. /// public static bool HasBinding(FrameworkElement element, DependencyProperty property) { -#if NET +#if NET || NETCOREAPP return BindingOperations.GetBindingBase(element, property) != null; #else return element.GetBindingExpression(property) != null; diff --git a/src/Caliburn.Micro.Platform/Platforms/net46-netcore/AssemblyInfo.cs b/src/Caliburn.Micro.Platform/Platforms/net46-netcore/AssemblyInfo.cs new file mode 100644 index 00000000..a7246838 --- /dev/null +++ b/src/Caliburn.Micro.Platform/Platforms/net46-netcore/AssemblyInfo.cs @@ -0,0 +1,8 @@ +using System.Runtime.InteropServices; +using System.Windows.Markup; + +[assembly: Guid("6449e9cb-4d4d-4d79-8f73-71a2fc647109")] +[assembly: XmlnsDefinition("http://www.caliburnproject.org", "Caliburn.Micro")] +[assembly: XmlnsPrefix("http://www.caliburnproject.org", "cal")] +[assembly: XmlnsDefinition("http://caliburnmicro.com", "Caliburn.Micro")] +[assembly: XmlnsPrefix("http://caliburnmicro.com", "cm")] diff --git a/src/Caliburn.Micro.Platform/Platforms/net46-netcore/AttachedCollection.cs b/src/Caliburn.Micro.Platform/Platforms/net46-netcore/AttachedCollection.cs new file mode 100644 index 00000000..18ff479d --- /dev/null +++ b/src/Caliburn.Micro.Platform/Platforms/net46-netcore/AttachedCollection.cs @@ -0,0 +1,85 @@ +namespace Caliburn.Micro { + using System.Collections.Specialized; + using System.Linq; + using System.Windows; + using Microsoft.Xaml.Behaviors; + + /// + /// A collection that can exist as part of a behavior. + /// + /// The type of item in the attached collection. + public class AttachedCollection : FreezableCollection, IAttachedObject + where T : DependencyObject, IAttachedObject { + DependencyObject associatedObject; + + /// + /// Creates an instance of + /// + public AttachedCollection() { + ((INotifyCollectionChanged)this).CollectionChanged += OnCollectionChanged; + } + + /// + /// Attached the collection. + /// + /// The dependency object to attach the collection to. + public void Attach(DependencyObject dependencyObject) { + WritePreamble(); + associatedObject = dependencyObject; + WritePostscript(); + + this.Apply(x => x.Attach(associatedObject)); + } + + /// + /// Detaches the collection. + /// + public void Detach() { + this.Apply(x => x.Detach()); + WritePreamble(); + associatedObject = null; + WritePostscript(); + } + + DependencyObject IAttachedObject.AssociatedObject { + get { return associatedObject; } + } + + /// + /// Called when an item is added from the collection. + /// + /// The item that was added. + protected virtual void OnItemAdded(T item) { + if (associatedObject != null) + item.Attach(associatedObject); + } + + /// + /// Called when an item is removed from the collection. + /// + /// The item that was removed. + protected virtual void OnItemRemoved(T item) { + if(item.AssociatedObject != null) + item.Detach(); + } + + void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) { + switch(e.Action) { + case NotifyCollectionChangedAction.Add: + e.NewItems.OfType().Where(x => !Contains(x)).Apply(OnItemAdded); + break; + case NotifyCollectionChangedAction.Remove: + e.OldItems.OfType().Apply(OnItemRemoved); + break; + case NotifyCollectionChangedAction.Replace: + e.OldItems.OfType().Apply(OnItemRemoved); + e.NewItems.OfType().Where(x => !Contains(x)).Apply(OnItemAdded); + break; + case NotifyCollectionChangedAction.Reset: + this.Apply(OnItemRemoved); + this.Apply(OnItemAdded); + break; + } + } + } +} diff --git a/src/Caliburn.Micro.Platform/Platforms/net46-netcore/Bootstrapper.cs b/src/Caliburn.Micro.Platform/Platforms/net46-netcore/Bootstrapper.cs new file mode 100644 index 00000000..e53b444f --- /dev/null +++ b/src/Caliburn.Micro.Platform/Platforms/net46-netcore/Bootstrapper.cs @@ -0,0 +1,222 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Threading; + +namespace Caliburn.Micro +{ + /// + /// Inherit from this class in order to customize the configuration of the framework. + /// + public abstract class BootstrapperBase + { + readonly bool useApplication; + bool isInitialized; + + /// + /// Creates an instance of the bootstrapper. + /// + /// Set this to false when hosting Caliburn.Micro inside and Office or WinForms application. The default is true. + protected BootstrapperBase(bool useApplication = true) + { + this.useApplication = useApplication; + } + + /// + /// The application. + /// + protected Application Application { get; set; } + + /// + /// Initialize the framework. + /// + public void Initialize() + { + if (isInitialized) + { + return; + } + + isInitialized = true; + + PlatformProvider.Current = new XamlPlatformProvider(); + + + var baseExtractTypes = AssemblySourceCache.ExtractTypes; + + AssemblySourceCache.ExtractTypes = assembly => + { + var baseTypes = baseExtractTypes(assembly); + var elementTypes = assembly.GetExportedTypes() + .Where(t => typeof(UIElement).IsAssignableFrom(t)); + + return baseTypes.Union(elementTypes); + }; + + AssemblySource.Instance.Refresh(); + + if (Execute.InDesignMode) + { + try + { + StartDesignTime(); + } + catch + { + //if something fails at design-time, there's really nothing we can do... + isInitialized = false; + throw; + } + } + else + { + StartRuntime(); + } + } + + /// + /// Called by the bootstrapper's constructor at design time to start the framework. + /// + protected virtual void StartDesignTime() + { + AssemblySource.Instance.Clear(); + AssemblySource.Instance.AddRange(SelectAssemblies()); + + Configure(); + IoC.GetInstance = GetInstance; + IoC.GetAllInstances = GetAllInstances; + IoC.BuildUp = BuildUp; + } + + /// + /// Called by the bootstrapper's constructor at runtime to start the framework. + /// + protected virtual void StartRuntime() + { + AssemblySourceCache.Install(); + AssemblySource.Instance.AddRange(SelectAssemblies()); + + if (useApplication) + { + Application = Application.Current; + PrepareApplication(); + } + + Configure(); + IoC.GetInstance = GetInstance; + IoC.GetAllInstances = GetAllInstances; + IoC.BuildUp = BuildUp; + } + + /// + /// Provides an opportunity to hook into the application object. + /// + protected virtual void PrepareApplication() + { + Application.Startup += OnStartup; + + Application.DispatcherUnhandledException += OnUnhandledException; + + Application.Exit += OnExit; + } + + /// + /// Override to configure the framework and setup your IoC container. + /// + protected virtual void Configure() + { + } + + /// + /// Override to tell the framework where to find assemblies to inspect for views, etc. + /// + /// A list of assemblies to inspect. + protected virtual IEnumerable SelectAssemblies() + { + return new[] {GetType().Assembly}; + } + + /// + /// Override this to provide an IoC specific implementation. + /// + /// The service to locate. + /// The key to locate. + /// The located service. + protected virtual object GetInstance(Type service, string key) + { + if (service == typeof(IWindowManager)) + service = typeof(WindowManager); + + return Activator.CreateInstance(service); + } + + /// + /// Override this to provide an IoC specific implementation + /// + /// The service to locate. + /// The located services. + protected virtual IEnumerable GetAllInstances(Type service) + { + return new[] {Activator.CreateInstance(service)}; + } + + /// + /// Override this to provide an IoC specific implementation. + /// + /// The instance to perform injection on. + protected virtual void BuildUp(object instance) + { + } + + /// + /// Override this to add custom behavior to execute after the application starts. + /// + /// The sender. + /// The args. + protected virtual void OnStartup(object sender, StartupEventArgs e) + { + } + + /// + /// Override this to add custom behavior on exit. + /// + /// The sender. + /// The event args. + protected virtual void OnExit(object sender, EventArgs e) + { + } + + /// + /// Override this to add custom behavior for unhandled exceptions. + /// + /// The sender. + /// The event args. + protected virtual void OnUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e) + { + } + + /// + /// Locates the view model, locates the associate view, binds them and shows it as the root view. + /// + /// The view model type. + /// The optional window settings. + protected async Task DisplayRootViewForAsync(Type viewModelType, IDictionary settings = null) + { + var windowManager = IoC.Get(); + await windowManager.ShowWindowAsync(IoC.GetInstance(viewModelType, null), null, settings); + } + + /// + /// Locates the view model, locates the associate view, binds them and shows it as the root view. + /// + /// The view model type. + /// The optional window settings. + protected Task DisplayRootViewFor(IDictionary settings = null) + { + return DisplayRootViewForAsync(typeof(TViewModel), settings); + } + } +} diff --git a/src/Caliburn.Micro.Platform/Platforms/net46-netcore/INavigationService.cs b/src/Caliburn.Micro.Platform/Platforms/net46-netcore/INavigationService.cs new file mode 100644 index 00000000..676f0fc7 --- /dev/null +++ b/src/Caliburn.Micro.Platform/Platforms/net46-netcore/INavigationService.cs @@ -0,0 +1,378 @@ +using System; +using System.Collections.Generic; +using System.Threading; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Navigation; + +namespace Caliburn.Micro +{ + /// + /// Implemented by services that provide based navigation. + /// + public interface INavigationService + { + /// + /// Navigates to the view represented by the given view model. + /// + /// The view model to navigate to. + /// Extra data to populate the view model with. + void NavigateToViewModel(Type viewModel, object extraData = null); + + /// + /// Navigates to the view represented by the given view model. + /// + /// The view model to navigate to. + /// Extra data to populate the view model with. + void NavigateToViewModel(object extraData = null); + + /// + /// Indicates whether the navigator can navigate back. + /// + bool CanGoBack { get; } + + /// + /// Indicates whether the navigator can navigate forward. + /// + bool CanGoForward { get; } + + /// + /// The current content. + /// + object CurrentContent { get; } + + /// + /// Stops the loading process. + /// + void StopLoading(); + + /// + /// Navigates back. + /// + void GoBack(); + + /// + /// Navigates forward. + /// + void GoForward(); + + /// + /// Removes the most recent entry from the back stack. + /// + /// The entry that was removed. + JournalEntry RemoveBackEntry(); + + /// + /// Raised after navigation. + /// + event NavigatedEventHandler Navigated; + + /// + /// Raised prior to navigation. + /// + event NavigatingCancelEventHandler Navigating; + + /// + /// Raised when navigation fails. + /// + event NavigationFailedEventHandler NavigationFailed; + + /// + /// Raised when navigation is stopped. + /// + event NavigationStoppedEventHandler NavigationStopped; + + /// + /// Raised when a fragment navigation occurs. + /// + event FragmentNavigationEventHandler FragmentNavigation; + } + + /// + /// A basic implementation of designed to adapt the control. + /// + public class FrameAdapter : INavigationService + { + readonly Frame frame; + readonly bool treatViewAsLoaded; + event NavigatingCancelEventHandler ExternalNavigatingHandler = delegate { }; + + /// + /// Creates an instance of + /// + /// The frame to represent as a . + /// Tells the frame adapter to assume that the view has already been loaded by the time OnNavigated is called. This is necessary when using the TransitionFrame. + public FrameAdapter(Frame frame, bool treatViewAsLoaded = false) + { + this.frame = frame; + this.treatViewAsLoaded = treatViewAsLoaded; + this.frame.Navigating += OnNavigating; + this.frame.Navigated += OnNavigated; + } + + /// + /// Occurs before navigation + /// + /// The event sender. + /// The event args. + protected virtual async void OnNavigating(object sender, NavigatingCancelEventArgs e) + { + ExternalNavigatingHandler(sender, e); + if (e.Cancel) + { + return; + } + + var fe = frame.Content as FrameworkElement; + if (fe == null) + { + return; + } + + if (fe.DataContext is IGuardClose guard) + { + var canClose = await guard.CanCloseAsync(CancellationToken.None); + + if (!canClose) + { + e.Cancel = true; + return; + } + } + + var deactivator = fe.DataContext as IDeactivate; + + // If we are navigating to the same page there is no need to deactivate + // e.g. When the app is activated with Fast Switch + if (deactivator != null && frame.CurrentSource != e.Uri) + { + await deactivator.DeactivateAsync(CanCloseOnNavigating(sender, e), CancellationToken.None); + } + } + + /// + /// Called to check whether or not to close current instance on navigating. + /// + /// The event sender from OnNavigating event. + /// The event args from OnNavigating event. + protected virtual bool CanCloseOnNavigating(object sender, NavigatingCancelEventArgs e) + { + return false; + } + + /// + /// Occurs after navigation + /// + /// The event sender. + /// The event args. + protected virtual async void OnNavigated(object sender, NavigationEventArgs e) + { + if (e.Uri.IsAbsoluteUri || e.Content == null) + { + return; + } + + ViewLocator.InitializeComponent(e.Content); + + var viewModel = ViewModelLocator.LocateForView(e.Content); + if (viewModel == null) + { + return; + } + + var page = e.Content as Page; + if (page == null) + { + throw new ArgumentException("View '" + e.Content.GetType().FullName + "' should inherit from Page or one of its descendents."); + } + + if (treatViewAsLoaded) + { + page.SetValue(View.IsLoadedProperty, true); + } + + TryInjectParameters(viewModel, e.ExtraData); + ViewModelBinder.Bind(viewModel, page, null); + + if (viewModel is IActivate activator) + { + await activator.ActivateAsync(); + } + + GC.Collect(); + } + + /// + /// Attempts to inject query string parameters from the view into the view model. + /// + /// The view model. + /// The parameter. + protected virtual void TryInjectParameters(object viewModel, object parameter) + { + var viewModelType = viewModel.GetType(); + + var dictionaryParameter = parameter as IDictionary; + + if (dictionaryParameter != null) + { + foreach (var pair in dictionaryParameter) + { + var property = viewModelType.GetPropertyCaseInsensitive(pair.Key); + + if (property == null) + { + continue; + } + + property.SetValue(viewModel, MessageBinder.CoerceValue(property.PropertyType, pair.Value, null), null); + } + } + else + { + var property = viewModelType.GetPropertyCaseInsensitive("Parameter"); + + if (property == null) + return; + + property.SetValue(viewModel, MessageBinder.CoerceValue(property.PropertyType, parameter, null), null); + } + } + + /// + /// The source. + /// + public Uri Source + { + get { return frame.Source; } + set { frame.Source = value; } + } + + /// + /// Indicates whether the navigator can navigate back. + /// + public bool CanGoBack + { + get { return frame.CanGoBack; } + } + + /// + /// Indicates whether the navigator can navigate forward. + /// + public bool CanGoForward + { + get { return frame.CanGoForward; } + } + + /// + /// The current source. + /// + public Uri CurrentSource + { + get { return frame.CurrentSource; } + } + + /// + /// The current content. + /// + public object CurrentContent + { + get { return frame.Content; } + } + + /// + /// Stops the loading process. + /// + public void StopLoading() + { + frame.StopLoading(); + } + + /// + /// Navigates back. + /// + public void GoBack() + { + frame.GoBack(); + } + + /// + /// Navigates forward. + /// + public void GoForward() + { + frame.GoForward(); + } + + /// + public void NavigateToViewModel(Type viewModel, object extraData = null) + { + var viewType = ViewLocator.LocateTypeForModelType(viewModel, null, null); + + var packUri = ViewLocator.DeterminePackUriFromType(viewModel, viewType); + + var uri = new Uri(packUri, UriKind.Relative); + + frame.Navigate(uri, extraData); + } + + /// + public void NavigateToViewModel(object extraData = null) + { + NavigateToViewModel(typeof(TViewModel), extraData); + } + + /// + /// Removes the most recent entry from the back stack. + /// + /// The entry that was removed. + public JournalEntry RemoveBackEntry() + { + return frame.RemoveBackEntry(); + } + + /// + /// Raised after navigation. + /// + public event NavigatedEventHandler Navigated + { + add { frame.Navigated += value; } + remove { frame.Navigated -= value; } + } + + /// + /// Raised prior to navigation. + /// + public event NavigatingCancelEventHandler Navigating + { + add { ExternalNavigatingHandler += value; } + remove { ExternalNavigatingHandler -= value; } + } + + /// + /// Raised when navigation fails. + /// + public event NavigationFailedEventHandler NavigationFailed + { + add { frame.NavigationFailed += value; } + remove { frame.NavigationFailed -= value; } + } + + /// + /// Raised when navigation is stopped. + /// + public event NavigationStoppedEventHandler NavigationStopped + { + add { frame.NavigationStopped += value; } + remove { frame.NavigationStopped -= value; } + } + + /// + /// Raised when a fragment navigation occurs. + /// + public event FragmentNavigationEventHandler FragmentNavigation + { + add { frame.FragmentNavigation += value; } + remove { frame.FragmentNavigation -= value; } + } + } +} diff --git a/src/Caliburn.Micro.Platform/Platforms/net46-netcore/NavigationExtensions.cs b/src/Caliburn.Micro.Platform/Platforms/net46-netcore/NavigationExtensions.cs new file mode 100644 index 00000000..13f7e629 --- /dev/null +++ b/src/Caliburn.Micro.Platform/Platforms/net46-netcore/NavigationExtensions.cs @@ -0,0 +1,21 @@ +using System; + +namespace Caliburn.Micro +{ + /// + /// Extension methods related to navigation. + /// + public static class NavigationExtensions + { + /// + /// Creates a Uri builder based on a view model type. + /// + /// The type of the view model. + /// The navigation service. + /// The builder. + public static NavigationHelper For(this INavigationService navigationService) + { + return new NavigationHelper().AttachTo(navigationService); + } + } +} \ No newline at end of file diff --git a/src/Caliburn.Micro.Platform/Platforms/net46-netcore/NavigationHelper.cs b/src/Caliburn.Micro.Platform/Platforms/net46-netcore/NavigationHelper.cs new file mode 100644 index 00000000..950cc986 --- /dev/null +++ b/src/Caliburn.Micro.Platform/Platforms/net46-netcore/NavigationHelper.cs @@ -0,0 +1,55 @@ +namespace Caliburn.Micro +{ + using System; + using System.Collections.Generic; + using System.Linq; + using System.Linq.Expressions; + + /// + /// Builds a Uri in a strongly typed fashion, based on a ViewModel. + /// + /// + public class NavigationHelper + { + readonly Dictionary queryString = new Dictionary(); + INavigationService navigationService; + + /// + /// Adds a query string parameter to the Uri. + /// + /// The type of the value. + /// The property. + /// The property value. + /// Itself + public NavigationHelper WithParam(Expression> property, TValue value) + { + queryString[property.GetMemberInfo().Name] = value; + + return this; + } + + /// + /// Attaches a navigation servies to this builder. + /// + /// The navigation service. + /// Itself + public NavigationHelper AttachTo(INavigationService navigationService) + { + this.navigationService = navigationService; + return this; + } + + /// + /// Navigates to the Uri represented by this builder. + /// + public void Navigate() + { + if (navigationService == null) + { + throw new InvalidOperationException("Cannot navigate without attaching an INavigationService. Call AttachTo first."); + } + + navigationService.NavigateToViewModel(queryString); + } + } +} diff --git a/src/Caliburn.Micro.Platform/Platforms/net46-netcore/Parameter.cs b/src/Caliburn.Micro.Platform/Platforms/net46-netcore/Parameter.cs new file mode 100644 index 00000000..e00344c1 --- /dev/null +++ b/src/Caliburn.Micro.Platform/Platforms/net46-netcore/Parameter.cs @@ -0,0 +1,88 @@ +namespace Caliburn.Micro { + using System; + using System.ComponentModel; + using System.Windows; + using Microsoft.Xaml.Behaviors; + + /// + /// Represents a parameter of an . + /// + public class Parameter : Freezable, IAttachedObject { + /// + /// A dependency property representing the parameter's value. + /// + public static readonly DependencyProperty ValueProperty = + DependencyProperty.Register( + "Value", + typeof(object), + typeof(Parameter), + new PropertyMetadata(OnValueChanged) + ); + + DependencyObject associatedObject; + WeakReference owner; + + /// + /// Gets or sets the value of the parameter. + /// + /// The value. + [Category("Common Properties")] + public object Value { + get { return GetValue(ValueProperty); } + set { SetValue(ValueProperty, value); } + } + + DependencyObject IAttachedObject.AssociatedObject { + get + { + ReadPreamble(); + return associatedObject; + } + } + + /// + /// Gets or sets the owner. + /// + protected ActionMessage Owner { + get { return owner == null ? null : owner.Target as ActionMessage; } + set { owner = new WeakReference(value); } + } + + void IAttachedObject.Attach(DependencyObject dependencyObject) { + WritePreamble(); + associatedObject = dependencyObject; + WritePostscript(); + } + + void IAttachedObject.Detach() { + WritePreamble(); + associatedObject = null; + WritePostscript(); + } + + /// + /// When implemented in a derived class, creates a new instance of the derived class. + /// + /// The new instance. + protected override Freezable CreateInstanceCore() { + return new Parameter(); + } + + /// + /// Makes the parameter aware of the that it's attached to. + /// + /// The action message. + internal void MakeAwareOf(ActionMessage owner) { + Owner = owner; + } + + static void OnValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { + var parameter = (Parameter)d; + var owner = parameter.Owner; + + if (owner != null) { + owner.UpdateAvailability(); + } + } + } +} diff --git a/src/Caliburn.Micro.Platform/Platforms/net46-netcore/WindowManager.cs b/src/Caliburn.Micro.Platform/Platforms/net46-netcore/WindowManager.cs new file mode 100644 index 00000000..e27316d7 --- /dev/null +++ b/src/Caliburn.Micro.Platform/Platforms/net46-netcore/WindowManager.cs @@ -0,0 +1,431 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Controls.Primitives; +using System.Windows.Data; +using System.Windows.Navigation; + +namespace Caliburn.Micro +{ + /// + /// A service that manages windows. + /// + public interface IWindowManager + { + /// + /// Shows a modal dialog for the specified model. + /// + /// The root model. + /// The context. + /// The optional dialog settings. + /// The dialog result. + Task ShowDialogAsync(object rootModel, object context = null, IDictionary settings = null); + + /// + /// Shows a non-modal window for the specified model. + /// + /// The root model. + /// The context. + /// The optional window settings. + Task ShowWindowAsync(object rootModel, object context = null, IDictionary settings = null); + + /// + /// Shows a popup at the current mouse position. + /// + /// The root model. + /// The view context. + /// The optional popup settings. + Task ShowPopupAsync(object rootModel, object context = null, IDictionary settings = null); + } + + /// + /// A service that manages windows. + /// + public class WindowManager : IWindowManager + { + /// + /// Shows a modal dialog for the specified model. + /// + /// The root model. + /// The context. + /// The dialog popup settings. + /// The dialog result. + public virtual async Task ShowDialogAsync(object rootModel, object context = null, IDictionary settings = null) + { + var window = await CreateWindowAsync(rootModel, true, context, settings); + + return window.ShowDialog(); + } + + /// + /// Shows a window for the specified model. + /// + /// The root model. + /// The context. + /// The optional window settings. + public virtual async Task ShowWindowAsync(object rootModel, object context = null, IDictionary settings = null) + { + NavigationWindow navWindow = null; + + var application = Application.Current; + if (application != null && application.MainWindow != null) + { + navWindow = application.MainWindow as NavigationWindow; + } + + if (navWindow != null) + { + var window = await CreatePageAsync(rootModel, context, settings); + navWindow.Navigate(window); + } + else + { + var window = await CreateWindowAsync(rootModel, false, context, settings); + + window.Show(); + } + } + + /// + /// Shows a popup at the current mouse position. + /// + /// The root model. + /// The view context. + /// The optional popup settings. + public virtual async Task ShowPopupAsync(object rootModel, object context = null, IDictionary settings = null) + { + var popup = CreatePopup(rootModel, settings); + var view = ViewLocator.LocateForModel(rootModel, popup, context); + + popup.Child = view; + popup.SetValue(View.IsGeneratedProperty, true); + + ViewModelBinder.Bind(rootModel, popup, null); + Action.SetTargetWithoutContext(view, rootModel); + + if (rootModel is IActivate activator) + { + await activator.ActivateAsync(); + } + + if (rootModel is IDeactivate deactivator) + { + popup.Closed += async (s, e) => await deactivator.DeactivateAsync(true); + } + + popup.IsOpen = true; + popup.CaptureMouse(); + } + + /// + /// Creates a popup for hosting a popup window. + /// + /// The model. + /// The optional popup settings. + /// The popup. + protected virtual Popup CreatePopup(object rootModel, IDictionary settings) + { + var popup = new Popup(); + + if (ApplySettings(popup, settings)) + { + if (!settings.ContainsKey("PlacementTarget") && !settings.ContainsKey("Placement")) + { + popup.Placement = PlacementMode.MousePoint; + } + + if (!settings.ContainsKey("AllowsTransparency")) + { + popup.AllowsTransparency = true; + } + } + else + { + popup.AllowsTransparency = true; + popup.Placement = PlacementMode.MousePoint; + } + + return popup; + } + + /// + /// Creates a window. + /// + /// The view model. + /// Whethor or not the window is being shown as a dialog. + /// The view context. + /// The optional popup settings. + /// The window. + protected virtual async Task CreateWindowAsync(object rootModel, bool isDialog, object context, IDictionary settings) + { + var view = EnsureWindow(rootModel, ViewLocator.LocateForModel(rootModel, null, context), isDialog); + ViewModelBinder.Bind(rootModel, view, context); + + var haveDisplayName = rootModel as IHaveDisplayName; + if (string.IsNullOrEmpty(view.Title) && haveDisplayName != null && !ConventionManager.HasBinding(view, Window.TitleProperty)) + { + var binding = new Binding("DisplayName") { Mode = BindingMode.TwoWay }; + view.SetBinding(Window.TitleProperty, binding); + } + + ApplySettings(view, settings); + + var conductor = new WindowConductor(rootModel, view); + + await conductor.InitialiseAysnc(); + + return view; + } + + /// + /// Makes sure the view is a window is is wrapped by one. + /// + /// The view model. + /// The view. + /// Whethor or not the window is being shown as a dialog. + /// The window. + protected virtual Window EnsureWindow(object model, object view, bool isDialog) + { + + if (view is Window window) + { + var owner = InferOwnerOf(window); + if (owner != null && isDialog) + { + window.Owner = owner; + } + } + else + { + window = new Window + { + Content = view, + SizeToContent = SizeToContent.WidthAndHeight + }; + + window.SetValue(View.IsGeneratedProperty, true); + + var owner = InferOwnerOf(window); + if (owner != null) + { + window.WindowStartupLocation = WindowStartupLocation.CenterOwner; + window.Owner = owner; + } + else + { + window.WindowStartupLocation = WindowStartupLocation.CenterScreen; + } + } + + return window; + } + + /// + /// Infers the owner of the window. + /// + /// The window to whose owner needs to be determined. + /// The owner. + protected virtual Window InferOwnerOf(Window window) + { + var application = Application.Current; + if (application == null) + { + return null; + } + + var active = application.Windows.OfType().FirstOrDefault(x => x.IsActive); + active = active ?? (PresentationSource.FromVisual(application.MainWindow) == null ? null : application.MainWindow); + return active == window ? null : active; + } + + /// + /// Creates the page. + /// + /// The root model. + /// The context. + /// The optional popup settings. + /// The page. + public virtual async Task CreatePageAsync(object rootModel, object context, IDictionary settings) + { + var view = EnsurePage(rootModel, ViewLocator.LocateForModel(rootModel, null, context)); + ViewModelBinder.Bind(rootModel, view, context); + + var haveDisplayName = rootModel as IHaveDisplayName; + if (string.IsNullOrEmpty(view.Title) && haveDisplayName != null && !ConventionManager.HasBinding(view, Page.TitleProperty)) + { + var binding = new Binding("DisplayName") { Mode = BindingMode.TwoWay }; + view.SetBinding(Page.TitleProperty, binding); + } + + ApplySettings(view, settings); + + if (rootModel is IActivate activator) + { + await activator.ActivateAsync(); + } + + if (rootModel is IDeactivate deactivatable) + { + view.Unloaded += async (s, e) => await deactivatable.DeactivateAsync(true); + } + + return view; + } + + /// + /// Ensures the view is a page or provides one. + /// + /// The model. + /// The view. + /// The page. + protected virtual Page EnsurePage(object model, object view) + { + if (view is Page page) + { + return page; + } + + page = new Page { Content = view }; + page.SetValue(View.IsGeneratedProperty, true); + + return page; + } + + private bool ApplySettings(object target, IEnumerable> settings) + { + if (settings != null) + { + var type = target.GetType(); + + foreach (var pair in settings) + { + var propertyInfo = type.GetProperty(pair.Key); + + if (propertyInfo != null) + { + propertyInfo.SetValue(target, pair.Value, null); + } + } + + return true; + } + + return false; + } + + private class WindowConductor + { + private bool deactivatingFromView; + private bool deactivateFromViewModel; + private bool actuallyClosing; + private readonly Window view; + private readonly object model; + + public WindowConductor(object model, Window view) + { + this.model = model; + this.view = view; + } + + public async Task InitialiseAysnc() + { + if (model is IActivate activator) + { + await activator.ActivateAsync(); + } + + if (model is IDeactivate deactivatable) + { + view.Closed += Closed; + deactivatable.Deactivated += Deactivated; + } + + if (model is IGuardClose guard) + { + view.Closing += Closing; + } + } + + private async void Closed(object sender, EventArgs e) + { + view.Closed -= Closed; + view.Closing -= Closing; + + if (deactivateFromViewModel) + { + return; + } + + var deactivatable = (IDeactivate)model; + + deactivatingFromView = true; + await deactivatable.DeactivateAsync(true); + deactivatingFromView = false; + } + + private void Deactivated(object sender, DeactivationEventArgs e) + { + if (!e.WasClosed) + { + return; + } + + ((IDeactivate)model).Deactivated -= Deactivated; + + if (deactivatingFromView) + { + return; + } + + deactivateFromViewModel = true; + actuallyClosing = true; + view.Close(); + actuallyClosing = false; + deactivateFromViewModel = false; + } + + private async void Closing(object sender, CancelEventArgs e) + { + if (e.Cancel) + { + return; + } + + var guard = (IGuardClose)model; + + if (actuallyClosing) + { + actuallyClosing = false; + return; + } + + var cachedDialogResult = view.DialogResult; + + e.Cancel = true; + + await Task.Yield(); + + var canClose = await guard.CanCloseAsync(CancellationToken.None); + + if (!canClose) + return; + + actuallyClosing = true; + + if (cachedDialogResult == null) + { + view.Close(); + } + else if (view.DialogResult != cachedDialogResult) + { + view.DialogResult = cachedDialogResult; + } + } + } + } +} diff --git a/src/global.json b/src/global.json index eca09e09..dc03d9ee 100644 --- a/src/global.json +++ b/src/global.json @@ -1,5 +1,5 @@ { "msbuild-sdks": { - "MSBuild.Sdk.Extras": "1.6.55" + "MSBuild.Sdk.Extras": "2.0.31" } } \ No newline at end of file From 3f2ba0f63ab10805dd3c9657d26ac65c0ca3ef5c Mon Sep 17 00:00:00 2001 From: Marcel Juen Date: Fri, 9 Aug 2019 19:40:14 +0200 Subject: [PATCH 2/6] Added missing NETCOREAPP for conditional code --- src/Caliburn.Micro.Platform/ConventionManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Caliburn.Micro.Platform/ConventionManager.cs b/src/Caliburn.Micro.Platform/ConventionManager.cs index 0d01062b..6e9071bf 100644 --- a/src/Caliburn.Micro.Platform/ConventionManager.cs +++ b/src/Caliburn.Micro.Platform/ConventionManager.cs @@ -177,7 +177,7 @@ public static class ConventionManager { /// Determines whether a custom update source trigger should be applied to the binding. /// public static Action ApplyUpdateSourceTrigger = (bindableProperty, element, binding, info) => { -#if WINDOWS_UWP || NET +#if WINDOWS_UWP || NET || NETCOREAPP binding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged; #endif }; From df87adaac6208f07ea8fd727e5c2a2eed75512de Mon Sep 17 00:00:00 2001 From: Marcel Juen Date: Wed, 14 Aug 2019 01:34:19 +0200 Subject: [PATCH 3/6] Replaced NETCOREAPP symbol with NETCORE defined in Directory.Build.targets --- src/Caliburn.Micro.Platform/ActionMessage.cs | 2 +- src/Caliburn.Micro.Platform/Bind.cs | 2 +- src/Caliburn.Micro.Platform/BindingScope.cs | 2 +- src/Caliburn.Micro.Platform/Caliburn.Micro.Platform.csproj | 4 ---- src/Caliburn.Micro.Platform/ConventionManager.cs | 4 ++-- src/Directory.Build.targets | 5 ++++- 6 files changed, 9 insertions(+), 10 deletions(-) diff --git a/src/Caliburn.Micro.Platform/ActionMessage.cs b/src/Caliburn.Micro.Platform/ActionMessage.cs index 2dbf0131..e75b70ed 100644 --- a/src/Caliburn.Micro.Platform/ActionMessage.cs +++ b/src/Caliburn.Micro.Platform/ActionMessage.cs @@ -191,7 +191,7 @@ void ElementLoaded(object sender, RoutedEventArgs e) { } else currentElement = context.View; -#if NET || NETCOREAPP +#if NET || NETCORE var binding = new Binding { Path = new PropertyPath(Message.HandlerProperty), Source = currentElement diff --git a/src/Caliburn.Micro.Platform/Bind.cs b/src/Caliburn.Micro.Platform/Bind.cs index 03c87b31..478e95d7 100644 --- a/src/Caliburn.Micro.Platform/Bind.cs +++ b/src/Caliburn.Micro.Platform/Bind.cs @@ -154,7 +154,7 @@ static void ModelWithoutContextChanged(DependencyObject d, DependencyPropertyCha /// /// The ui to apply conventions to. /// Whether or not conventions are applied. -#if NET || NETCOREAPP +#if NET || NETCORE [AttachedPropertyBrowsableForTypeAttribute(typeof(DependencyObject))] #endif public static bool GetAtDesignTime(DependencyObject dependencyObject) { diff --git a/src/Caliburn.Micro.Platform/BindingScope.cs b/src/Caliburn.Micro.Platform/BindingScope.cs index 34d27146..8ba20662 100644 --- a/src/Caliburn.Micro.Platform/BindingScope.cs +++ b/src/Caliburn.Micro.Platform/BindingScope.cs @@ -169,7 +169,7 @@ public static bool RemoveChildResolver(ChildResolver resolver) { continue; } -#if NET || NETCOREAPP +#if NET || NETCORE var childCount = (current is Visual || current is Visual3D) ? VisualTreeHelper.GetChildrenCount(current) : 0; #else diff --git a/src/Caliburn.Micro.Platform/Caliburn.Micro.Platform.csproj b/src/Caliburn.Micro.Platform/Caliburn.Micro.Platform.csproj index a1280721..820dcf92 100644 --- a/src/Caliburn.Micro.Platform/Caliburn.Micro.Platform.csproj +++ b/src/Caliburn.Micro.Platform/Caliburn.Micro.Platform.csproj @@ -79,8 +79,4 @@ - - - - diff --git a/src/Caliburn.Micro.Platform/ConventionManager.cs b/src/Caliburn.Micro.Platform/ConventionManager.cs index 6e9071bf..79760ca4 100644 --- a/src/Caliburn.Micro.Platform/ConventionManager.cs +++ b/src/Caliburn.Micro.Platform/ConventionManager.cs @@ -177,7 +177,7 @@ public static class ConventionManager { /// Determines whether a custom update source trigger should be applied to the binding. /// public static Action ApplyUpdateSourceTrigger = (bindableProperty, element, binding, info) => { -#if WINDOWS_UWP || NET || NETCOREAPP +#if WINDOWS_UWP || NET || NETCORE binding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged; #endif }; @@ -363,7 +363,7 @@ public static ElementConvention GetElementConvention(Type elementType) { /// Determines whether a particular dependency property already has a binding on the provided element. /// public static bool HasBinding(FrameworkElement element, DependencyProperty property) { -#if NET || NETCOREAPP +#if NET || NETCORE return BindingOperations.GetBindingBase(element, property) != null; #else return element.GetBindingExpression(property) != null; diff --git a/src/Directory.Build.targets b/src/Directory.Build.targets index 11577896..8c412d2f 100644 --- a/src/Directory.Build.targets +++ b/src/Directory.Build.targets @@ -1,6 +1,9 @@ $(DefineConstants);NETSTANDARD + + + $(DefineConstants);NETCORE $(DefineConstants);NET @@ -25,4 +28,4 @@ - \ No newline at end of file + From b301d4df33cb7a590222ba8ab459ada2a1e2e3c4 Mon Sep 17 00:00:00 2001 From: Marcel Juen Date: Wed, 14 Aug 2019 12:13:47 +0200 Subject: [PATCH 4/6] Corrected indentation in Directory.Build.targets --- src/Directory.Build.targets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Directory.Build.targets b/src/Directory.Build.targets index 8c412d2f..9878dc78 100644 --- a/src/Directory.Build.targets +++ b/src/Directory.Build.targets @@ -2,7 +2,7 @@ $(DefineConstants);NETSTANDARD - + $(DefineConstants);NETCORE From 713dff0d51ad718e9042b0432c0090b919382016 Mon Sep 17 00:00:00 2001 From: Marcel Juen Date: Thu, 15 Aug 2019 23:25:29 +0200 Subject: [PATCH 5/6] Adjust azure pipeline to work with VS2019 and .NET Core 3.0 --- azure-pipeline.yml | 33 +++++++++++++------ .../Setup.Forms.Droid.csproj | 2 +- .../Caliburn.Micro.Core.csproj | 5 +++ .../Caliburn.Micro.Platform.csproj | 5 +++ src/global.json | 5 ++- 5 files changed, 38 insertions(+), 12 deletions(-) diff --git a/azure-pipeline.yml b/azure-pipeline.yml index 461311d4..5c801dc7 100644 --- a/azure-pipeline.yml +++ b/azure-pipeline.yml @@ -1,5 +1,5 @@ pool: - vmImage: vs2017-win2016 + vmImage: windows-2019 variables: buildConfiguration: Release @@ -9,6 +9,12 @@ variables: featuresSamplesSolution: 'samples\features\Features.sln' steps: +- task: UseDotNet@2 + displayName: 'Install .NET Core 3' + inputs: + packageType: 'sdk' + useGlobalJson: true + - task: DotNetCoreCLI@2 inputs: command: custom @@ -23,8 +29,15 @@ steps: displayName: Nuget Restore inputs: solution: '$(coreSolution)' - configuration: '$(buildConfiguration)' msbuildArgs: '/t:Restore' + configuration: '$(buildConfiguration)' + +- task: PowerShell@2 +# Workaround for https://github.com/onovotny/MSBuildSdkExtras/issues/174 + displayName: 'Resource.Designer workaround' + inputs: + targetType: 'inline' + script: 'New-Item -ItemType File -Path .\src\Caliburn.Micro.Core\obj\Release\MonoAndroid80\Resource.Designer.cs -Force' - task: VSBuild@1 displayName: Build & Pack Core Solution @@ -32,14 +45,14 @@ steps: solution: '$(coreSolution)' configuration: '$(buildConfiguration)' platform: '$(buildPlatform)' - msbuildArgs: '/t:Pack' + msbuildArgs: '/t:Pack /p:JavaSdkDirectory="$(JAVA_HOME)/"' -- task: VSTest@2 +- task: DotNetCoreCLI@2 displayName: Run Unit Tests inputs: - testAssemblyVer2: 'bin\**\*.Tests.dll' - configuration: '$(buildConfiguration)' - platform: '$(buildPlatform)' + command: test + projects: '**/*Test*/*.csproj' + arguments: '--configuration $(buildConfiguration) --collect "Code coverage"' - task: NuGetCommand@2 displayName: Restore Setup Solution @@ -52,7 +65,7 @@ steps: solution: '$(setupSamplesSolution)' configuration: '$(buildConfiguration)' platform: '$(buildPlatform)' - msbuildArgs: '/t:Build' + msbuildArgs: '/t:Build /p:JavaSdkDirectory="$(JAVA_HOME)/"' - task: NuGetCommand@2 displayName: Restore Features Solution @@ -65,7 +78,7 @@ steps: solution: '$(featuresSamplesSolution)' configuration: '$(buildConfiguration)' platform: '$(buildPlatform)' - msbuildArgs: '/t:Build' + msbuildArgs: '/t:Build /p:JavaSdkDirectory="$(JAVA_HOME)/"' - task: CopyFiles@2 displayName: Copy Packages to Artifact Directory @@ -77,4 +90,4 @@ steps: displayName: Publish Package Artifacts inputs: pathToPublish: '$(build.artifactStagingDirectory)' - artifactName: Packages \ No newline at end of file + artifactName: Packages diff --git a/samples/setup/Setup.Forms/Setup.Forms.Droid/Setup.Forms.Droid.csproj b/samples/setup/Setup.Forms/Setup.Forms.Droid/Setup.Forms.Droid.csproj index c4c567bb..4503408d 100644 --- a/samples/setup/Setup.Forms/Setup.Forms.Droid/Setup.Forms.Droid.csproj +++ b/samples/setup/Setup.Forms/Setup.Forms.Droid/Setup.Forms.Droid.csproj @@ -18,7 +18,7 @@ Properties\AndroidManifest.xml true v6.0 - armeabi,armeabi-v7a,x86 + armeabi-v7a,x86 diff --git a/src/Caliburn.Micro.Core/Caliburn.Micro.Core.csproj b/src/Caliburn.Micro.Core/Caliburn.Micro.Core.csproj index 37fe9609..4281ca1d 100644 --- a/src/Caliburn.Micro.Core/Caliburn.Micro.Core.csproj +++ b/src/Caliburn.Micro.Core/Caliburn.Micro.Core.csproj @@ -7,6 +7,11 @@ Caliburn.Micro + + + false + + .\..\Caliburn.Micro.snk true diff --git a/src/Caliburn.Micro.Platform/Caliburn.Micro.Platform.csproj b/src/Caliburn.Micro.Platform/Caliburn.Micro.Platform.csproj index 820dcf92..5b5ecb10 100644 --- a/src/Caliburn.Micro.Platform/Caliburn.Micro.Platform.csproj +++ b/src/Caliburn.Micro.Platform/Caliburn.Micro.Platform.csproj @@ -7,6 +7,11 @@ Caliburn.Micro + + + false + + XFORMS diff --git a/src/global.json b/src/global.json index dc03d9ee..cd91000f 100644 --- a/src/global.json +++ b/src/global.json @@ -1,5 +1,8 @@ { + "sdk": { + "version": "3.0.100-preview8-013656" + }, "msbuild-sdks": { "MSBuild.Sdk.Extras": "2.0.31" } -} \ No newline at end of file +} \ No newline at end of file From e81cd0b6f9044908eefb4baddbb09f757f6aef1b Mon Sep 17 00:00:00 2001 From: Marcel Juen Date: Thu, 15 Aug 2019 23:58:25 +0200 Subject: [PATCH 6/6] Fix certficate thumbprint for UWP sample project For more information about why this necessary take a look here http://www.rudyhuyn.com/blog/2019/08/05/how-to-fix-certificate-does-not-match-supplied-signing-thumbprint/ --- samples/features/Features.UWP/Features.UWP.csproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/samples/features/Features.UWP/Features.UWP.csproj b/samples/features/Features.UWP/Features.UWP.csproj index c3a2674e..7d977b7f 100644 --- a/samples/features/Features.UWP/Features.UWP.csproj +++ b/samples/features/Features.UWP/Features.UWP.csproj @@ -18,7 +18,7 @@ {A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} Features.UWP_TemporaryKey.pfx win10-arm;win10-arm-aot;win10-x86;win10-x86-aot;win10-x64;win10-x64-aot - B7A25D83EAD631188A9505D2D7C411770734C52B + 714bf81d767ae7aa7fcf3bb435b0804ad3eadb05 true @@ -268,4 +268,4 @@ --> - \ No newline at end of file +