diff --git a/src/Directory.build.props b/src/Directory.build.props index f286017e34..f593a6b1a0 100644 --- a/src/Directory.build.props +++ b/src/Directory.build.props @@ -48,11 +48,11 @@ - + - + diff --git a/src/ReactiveUI.AndroidX/ReactiveUI.AndroidX.csproj b/src/ReactiveUI.AndroidX/ReactiveUI.AndroidX.csproj index 5b6fc777d6..e7d6ce6c60 100644 --- a/src/ReactiveUI.AndroidX/ReactiveUI.AndroidX.csproj +++ b/src/ReactiveUI.AndroidX/ReactiveUI.AndroidX.csproj @@ -16,11 +16,11 @@ - - - - - + + + + + diff --git a/src/ReactiveUI.Blazor/ReactiveUI.Blazor.csproj b/src/ReactiveUI.Blazor/ReactiveUI.Blazor.csproj index 0d41680faf..41438348e7 100644 --- a/src/ReactiveUI.Blazor/ReactiveUI.Blazor.csproj +++ b/src/ReactiveUI.Blazor/ReactiveUI.Blazor.csproj @@ -10,11 +10,15 @@ - + - - + + + + + + diff --git a/src/ReactiveUI.Maui/ReactiveShell.cs b/src/ReactiveUI.Maui/ReactiveShell.cs new file mode 100644 index 0000000000..1c98d6a785 --- /dev/null +++ b/src/ReactiveUI.Maui/ReactiveShell.cs @@ -0,0 +1,54 @@ +// Copyright (c) 2022 .NET Foundation and Contributors. All rights reserved. +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for full license information. + +using Microsoft.Maui.Controls; + +namespace ReactiveUI.Maui; + +/// +/// ReactiveShell. +/// +/// The type of the view model. +/// +/// +public class ReactiveShell : Shell, IViewFor + where TViewModel : class +{ + /// + /// The view model bindable property. + /// + public static readonly BindableProperty ViewModelProperty = BindableProperty.Create( + nameof(ViewModel), + typeof(TViewModel), + typeof(ReactiveShell), + default(TViewModel), + BindingMode.OneWay, + propertyChanged: OnViewModelChanged); + + /// + /// Gets or sets the ViewModel to display. + /// + public TViewModel? ViewModel + { + get => (TViewModel)GetValue(ViewModelProperty); + set => SetValue(ViewModelProperty, value); + } + + /// + object? IViewFor.ViewModel + { + get => ViewModel; + set => ViewModel = (TViewModel?)value; + } + + /// + protected override void OnBindingContextChanged() + { + base.OnBindingContextChanged(); + ViewModel = BindingContext as TViewModel; + } + + private static void OnViewModelChanged(BindableObject bindableObject, object oldValue, object newValue) => bindableObject.BindingContext = newValue; +} diff --git a/src/ReactiveUI.Maui/ReactiveShellContent.cs b/src/ReactiveUI.Maui/ReactiveShellContent.cs new file mode 100644 index 0000000000..35bae0095d --- /dev/null +++ b/src/ReactiveUI.Maui/ReactiveShellContent.cs @@ -0,0 +1,95 @@ +// Copyright (c) 2022 .NET Foundation and Contributors. All rights reserved. +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for full license information. + +using System; +using Microsoft.Maui.Controls; +using Splat; + +namespace ReactiveUI.Maui; + +/// +/// ReactiveShellContent. +/// +/// The type of the view model. +/// +/// +public class ReactiveShellContent : ShellContent, IActivatableView + where TViewModel : class +{ + /// + /// The contract property. + /// + public static readonly BindableProperty ContractProperty = BindableProperty.Create( + nameof(Contract), + typeof(string), + typeof(ReactiveShellContent), + null, + BindingMode.Default, + propertyChanged: ViewModelChanged); + + /// + /// The view model property. + /// + public static readonly BindableProperty ViewModelProperty = BindableProperty.Create( + nameof(ViewModel), + typeof(TViewModel), + typeof(ReactiveShellContent), + default(TViewModel), + BindingMode.Default, + propertyChanged: ViewModelChanged); + + /// + /// Initializes a new instance of the class. + /// + public ReactiveShellContent() + { + var view = Locator.Current.GetService>(Contract); + if (view is not null) + { + ContentTemplate = new DataTemplate(() => view); + } + } + + /// + /// Gets or sets the view model. + /// + /// + /// The view model. + /// + public TViewModel? ViewModel + { + get => (TViewModel)GetValue(ViewModelProperty); + set => SetValue(ViewModelProperty, value); + } + + /// + /// Gets or sets the contract for the view. + /// + /// + /// The contract. + /// + public string? Contract + { + get => (string?)GetValue(ContractProperty); + set => SetValue(ContractProperty, value); + } + + private static void ViewModelChanged(BindableObject bindable, object oldValue, object newValue) + { + if (Locator.Current is null) + { + throw new NullReferenceException(nameof(Locator.Current)); + } + + if (bindable is ReactiveShellContent svm) + { + var view = Locator.Current.GetService>(svm.Contract); + if (view is not null) + { + svm.ContentTemplate = new DataTemplate(() => view); + } + } + } +} diff --git a/src/ReactiveUI.Tests/Platforms/winforms/API/WinformsApiApprovalTests.Winforms.DotNet6_0.verified.txt b/src/ReactiveUI.Tests/Platforms/winforms/API/WinformsApiApprovalTests.Winforms.DotNet6_0.verified.txt index c4fc4fb7f8..490296ccf6 100644 --- a/src/ReactiveUI.Tests/Platforms/winforms/API/WinformsApiApprovalTests.Winforms.DotNet6_0.verified.txt +++ b/src/ReactiveUI.Tests/Platforms/winforms/API/WinformsApiApprovalTests.Winforms.DotNet6_0.verified.txt @@ -1,4 +1,6 @@ -[assembly: System.Runtime.Versioning.TargetFramework(".NETFramework,Version=v4.6.2", FrameworkDisplayName=".NET Framework 4.6.2")] +[assembly: System.Runtime.Versioning.SupportedOSPlatform("Windows10.0.17763.0")] +[assembly: System.Runtime.Versioning.TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName=".NET 6.0")] +[assembly: System.Runtime.Versioning.TargetPlatform("Windows10.0.17763.0")] namespace ReactiveUI.Winforms { public class ActivationForViewFetcher : ReactiveUI.IActivationForViewFetcher, Splat.IEnableLogger @@ -106,4 +108,12 @@ namespace ReactiveUI.Winforms public int GetAffinityForObject(System.Type type, string propertyName, bool beforeChanged = false) { } public System.IObservable> GetNotificationForProperty(object sender, System.Linq.Expressions.Expression expression, string propertyName, bool beforeChanged = false, bool suppressWarnings = false) { } } +} +namespace System.Reactive.Concurrency +{ + public class ControlScheduler : System.Reactive.Concurrency.LocalScheduler, System.Reactive.Concurrency.ISchedulerPeriodic { } +} +namespace System.Reactive.Linq +{ + public static class ControlObservable { } } \ No newline at end of file diff --git a/src/ReactiveUI.Tests/ReactiveUI.Tests.csproj b/src/ReactiveUI.Tests/ReactiveUI.Tests.csproj index c882b0aa48..426d7879ce 100644 --- a/src/ReactiveUI.Tests/ReactiveUI.Tests.csproj +++ b/src/ReactiveUI.Tests/ReactiveUI.Tests.csproj @@ -1,8 +1,8 @@ - + net462;net6.0 - net472;net6.0-windows + net472;net6.0-windows10.0.17763.0 $(NoWarn);CS1591