diff --git a/src/ReactiveUI.Tests/DependencyResolverTests.cs b/src/ReactiveUI.Tests/DependencyResolverTests.cs index 9101ed6005..439b55c06c 100644 --- a/src/ReactiveUI.Tests/DependencyResolverTests.cs +++ b/src/ReactiveUI.Tests/DependencyResolverTests.cs @@ -5,167 +5,181 @@ using ReactiveUI; using ReactiveUI.Tests; using Splat; - using Xunit; namespace ReactiveUI.Tests { - public class ExampleViewModel : ReactiveObject - { - } + public class ExampleViewModel : ReactiveObject + { + } - public class AnotherViewModel : ReactiveObject - { - } + public class AnotherViewModel : ReactiveObject + { + } - public class NeverUsedViewModel : ReactiveObject - { - } + public class NeverUsedViewModel : ReactiveObject + { + } - public class SingleInstanceExampleViewModel : ReactiveObject - { - } + public class SingleInstanceExampleViewModel : ReactiveObject + { + } - public class ViewModelWithWeirdName : ReactiveObject - { - } + public class ViewModelWithWeirdName : ReactiveObject + { + } - public class ExampleView : ReactiveUserControl - { - } + public class ExampleWindowViewModel : ReactiveObject + { + } - public class AnotherView : ReactiveUserControl - { - } + public class ExampleWindowView : ReactiveWindow + { + } + + public class ExampleView : ReactiveUserControl + { + } + + public class AnotherView : ReactiveUserControl + { + } + + [ViewContract("contract")] + public class ContractExampleView : ReactiveUserControl + { + } + + [SingleInstanceView] + public class NeverUsedView : ReactiveUserControl + { + public static int Instances; - [ViewContract("contract")] - public class ContractExampleView : ReactiveUserControl + public NeverUsedView() { + Instances++; } + } - [SingleInstanceView] - public class NeverUsedView : ReactiveUserControl - { - public static int Instances; + [SingleInstanceView] + public class SingleInstanceExampleView : ReactiveUserControl + { + public static int Instances; - public NeverUsedView() - { - Instances++; - } + public SingleInstanceExampleView() + { + Instances++; } + } - [SingleInstanceView] - public class SingleInstanceExampleView : ReactiveUserControl - { - public static int Instances; + [ViewContract("contract")] + [SingleInstanceView] + public class SingleInstanceWithContractExampleView : ReactiveUserControl + { + public static int Instances; - public SingleInstanceExampleView() { Instances++; } + public SingleInstanceWithContractExampleView() + { + Instances++; } + } - [ViewContract("contract")] - [SingleInstanceView] - public class SingleInstanceWithContractExampleView : ReactiveUserControl - { - public static int Instances; + public class ViewWithoutMatchingName : ReactiveUserControl + { + } - public SingleInstanceWithContractExampleView() { Instances++; } - } + public class DependencyResolverTests + { + private readonly IMutableDependencyResolver _resolver; - public class ViewWithoutMatchingName : ReactiveUserControl + public DependencyResolverTests() { + _resolver = new ModernDependencyResolver(); + _resolver.InitializeSplat(); + _resolver.InitializeReactiveUI(); + _resolver.RegisterViewsForViewModels(GetType().Assembly); } - public class DependencyResolverTests + [WpfFact] + public void RegisterViewsForViewModelShouldRegisterAllViews() { - private readonly IMutableDependencyResolver _resolver; - - public DependencyResolverTests() + using (_resolver.WithResolver()) { - _resolver = new ModernDependencyResolver(); - _resolver.InitializeSplat(); - _resolver.InitializeReactiveUI(); - _resolver.RegisterViewsForViewModels(GetType().Assembly); - } - - [WpfFact] - public void RegisterViewsForViewModelShouldRegisterAllViews() - { - using (_resolver.WithResolver()) - { - Assert.Single(_resolver.GetServices>()); - Assert.Single(_resolver.GetServices>()); - Assert.Single(_resolver.GetServices>()); - } + Assert.Single(_resolver.GetServices>()); + Assert.Single(_resolver.GetServices>()); + Assert.Single(_resolver.GetServices>()); + Assert.Single(_resolver.GetServices>()); } + } - [WpfFact] - public void RegisterViewsForViewModelShouldIncludeContracts() + [WpfFact] + public void RegisterViewsForViewModelShouldIncludeContracts() + { + using (_resolver.WithResolver()) { - using (_resolver.WithResolver()) - { - Assert.Single(_resolver.GetServices(typeof(IViewFor), "contract")); - } + Assert.Single(_resolver.GetServices(typeof(IViewFor), "contract")); } + } - [WpfFact] - public void NonContractRegistrationsShouldResolveCorrectly() + [WpfFact] + public void NonContractRegistrationsShouldResolveCorrectly() + { + using (_resolver.WithResolver()) { - using (_resolver.WithResolver()) - { - Assert.IsType(_resolver.GetService>()); - } + Assert.IsType(_resolver.GetService>()); } + } - [WpfFact] - public void ContractRegistrationsShouldResolveCorrectly() + [WpfFact] + public void ContractRegistrationsShouldResolveCorrectly() + { + using (_resolver.WithResolver()) { - using (_resolver.WithResolver()) - { - Assert.IsType(_resolver.GetService(typeof(IViewFor), "contract")); - } + Assert.IsType(_resolver.GetService(typeof(IViewFor), "contract")); } + } - [Fact] - public void SingleInstanceViewsShouldOnlyBeInstantiatedWhenRequested() + [Fact] + public void SingleInstanceViewsShouldOnlyBeInstantiatedWhenRequested() + { + using (_resolver.WithResolver()) { - using (_resolver.WithResolver()) - { - Assert.Equal(0, NeverUsedView.Instances); - } + Assert.Equal(0, NeverUsedView.Instances); } + } - [WpfFact] - public void SingleInstanceViewsShouldOnlyBeInstantiatedOnce() + [WpfFact] + public void SingleInstanceViewsShouldOnlyBeInstantiatedOnce() + { + using (_resolver.WithResolver()) { - using (_resolver.WithResolver()) - { - Assert.Equal(0, SingleInstanceExampleView.Instances); + Assert.Equal(0, SingleInstanceExampleView.Instances); - var instance = _resolver.GetService(typeof(IViewFor)); - Assert.Equal(1, SingleInstanceExampleView.Instances); + var instance = _resolver.GetService(typeof(IViewFor)); + Assert.Equal(1, SingleInstanceExampleView.Instances); - var instance2 = _resolver.GetService(typeof(IViewFor)); - Assert.Equal(1, SingleInstanceExampleView.Instances); + var instance2 = _resolver.GetService(typeof(IViewFor)); + Assert.Equal(1, SingleInstanceExampleView.Instances); - Assert.Same(instance, instance2); - } + Assert.Same(instance, instance2); } + } - [WpfFact] - public void SingleInstanceViewsWithContractShouldResolveCorrectly() + [WpfFact] + public void SingleInstanceViewsWithContractShouldResolveCorrectly() + { + using (_resolver.WithResolver()) { - using (_resolver.WithResolver()) - { - Assert.Equal(0, SingleInstanceWithContractExampleView.Instances); + Assert.Equal(0, SingleInstanceWithContractExampleView.Instances); - var instance = _resolver.GetService(typeof(IViewFor), "contract"); - Assert.Equal(1, SingleInstanceWithContractExampleView.Instances); + var instance = _resolver.GetService(typeof(IViewFor), "contract"); + Assert.Equal(1, SingleInstanceWithContractExampleView.Instances); - var instance2 = _resolver.GetService(typeof(IViewFor), "contract"); - Assert.Equal(1, SingleInstanceWithContractExampleView.Instances); + var instance2 = _resolver.GetService(typeof(IViewFor), "contract"); + Assert.Equal(1, SingleInstanceWithContractExampleView.Instances); - Assert.Same(instance, instance2); - } + Assert.Same(instance, instance2); } + } } } diff --git a/src/ReactiveUI.Wpf/ReactiveWindow.cs b/src/ReactiveUI.Wpf/ReactiveWindow.cs new file mode 100644 index 0000000000..9f00f6d0e6 --- /dev/null +++ b/src/ReactiveUI.Wpf/ReactiveWindow.cs @@ -0,0 +1,70 @@ +// 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 more information. + +using System.Windows; + +namespace ReactiveUI +{ + /// + /// A that is reactive. + /// + /// + /// + /// This class is a that is also reactive. That is, it implements . + /// You can extend this class to get an implementation of rather than writing one yourself. + /// + /// + /// Note that the XAML for your control must specify the same base class, including the generic argument you provide for your view + /// model. To do this, use the TypeArguments attribute as follows: + /// + /// + /// + /// + /// ]]> + /// + /// + /// + /// + /// The type of the view model backing the view. + /// + public abstract class ReactiveWindow : + Window, IViewFor + where TViewModel : class + { + /// + /// Gets the binding root view model. + /// + public TViewModel BindingRoot => ViewModel; + + /// + /// The view model dependency property. + /// + public static readonly DependencyProperty ViewModelProperty = + DependencyProperty.Register( + "ViewModel", + typeof(TViewModel), + typeof(ReactiveWindow), + new PropertyMetadata(null)); + + /// + public TViewModel ViewModel + { + get => (TViewModel)GetValue(ViewModelProperty); + set => SetValue(ViewModelProperty, value); + } + + /// + object IViewFor.ViewModel + { + get => ViewModel; + set => ViewModel = (TViewModel)value; + } + } +}