From cbe38c97b91637e00c3e81cce9e0353682740837 Mon Sep 17 00:00:00 2001 From: Glenn Watson <5834289+glennawatson@users.noreply.github.com> Date: Fri, 28 Dec 2018 04:50:59 -0800 Subject: [PATCH] housekeeping: Fix the majority of warnings in the project. (#1872) --- integrationtests/Directory.Build.props | 1 - src/ApiGeneratorGlobalSuppressions.cs | 161 +++++ src/Directory.build.props | 23 +- src/EventBuilder/DefaultTemplate.mustache | 9 + src/EventBuilder/Platforms/IPlatform.cs | 4 +- .../XamarinEssentialsTemplate.mustache | 15 +- .../ControlFetcherMixin.cs | 7 +- .../ReactiveAppCompatActivity.cs | 84 +-- .../ReactiveDialogFragment.cs | 24 +- .../ReactiveFragment.cs | 20 +- .../ReactiveFragmentActivity.cs | 44 +- .../ReactivePagerAdapter.cs | 34 +- .../ReactiveRecyclerViewAdapter.cs | 156 +--- .../ReactiveRecyclerViewViewHolder.cs | 157 ++++ .../ReactiveUI.AndroidSupport.csproj | 2 - .../FollowObservableStateBehavior.cs | 26 +- .../Platforms/net461/ObservableTrigger.cs | 34 +- .../Platforms/uap10.0.16299/Behavior.cs | 19 +- .../ObservableTriggerBehavior.cs | 108 +-- .../ReactiveUI.Events.WPF.csproj | 1 + .../ReactiveUI.Events.Winforms.csproj | 1 + .../ReactiveUI.Events.XamForms.csproj | 1 + .../ReactiveUI.Events.csproj | 1 + src/ReactiveUI.Events/SingleAwaitSubject.cs | 8 +- .../ReactiveDependencyAttribute.cs | 4 +- .../ReactiveUI.Fody.Helpers.csproj | 4 +- ...ApprovalTests.ReactiveUIFody.approved.txt} | 2 +- .../API/ApiApprovalTests.cs | 19 +- src/ReactiveUI.Fody.Tests/FodyWeavers.xml | 7 +- src/ReactiveUI.Fody.Tests/FodyWeavers.xsd | 26 + .../Issues/Issue10Tests.cs | 10 +- .../Issues/Issue11Tests.cs | 8 +- .../Issues/Issue13Tests.cs | 10 +- .../ObservableAsPropertyTests.cs | 6 +- .../ReactiveUI.Fody.Tests.csproj | 2 +- .../ObservableAsPropertyWeaver.cs | 8 +- .../ReactiveDependencyPropertyWeaver.cs | 4 +- src/ReactiveUI.Fody/ReactiveUI.Fody.csproj | 2 +- .../ReactiveUIPropertyWeaver.cs | 4 +- .../ApiApprovalTests.ReactiveUI.approved.txt | 7 +- .../ApiApprovalTests.Winforms.approved.txt | 16 +- src/ReactiveUI.Tests/API/ApiApprovalTests.cs | 18 +- src/ReactiveUI.Tests/AutoPersistHelperTest.cs | 75 +- src/ReactiveUI.Tests/AwaiterTest.cs | 12 +- .../ObservableAsPropertyHelperTest.cs | 12 +- .../ObservedChangedMixinTest.cs | 43 +- .../ActivationForViewFetcher.cs | 22 +- ...ng.cs => CreatesWinformsCommandBinding.cs} | 0 .../EventShims/PropertyChangedEventManager.cs | 15 + .../PropertyChangingEventManager.cs | 14 + .../IReactiveDerivedBindingList.cs | 23 + ...Mixins.cs => ObservableCollectionMixin.cs} | 126 +--- .../ReactiveBindingList.cs | 114 +-- .../ReactiveDerivedBindingList.cs | 93 +++ src/ReactiveUI.Winforms/RoutedViewHost.cs | 5 +- src/ReactiveUI.Winforms/ViewModelViewHost.cs | 19 +- .../WeakEventManagerShims.cs | 35 - ...oSuspendHelper.cs => AutoSuspendHelper.cs} | 10 +- ... DependencyObjectObservableForProperty.cs} | 2 +- src/ReactiveUI.Wpf/ReactiveUI.Wpf.csproj | 4 + src/ReactiveUI.Wpf/ReactiveWindow.cs | 10 +- .../TransitioningContentControl.cs | 50 +- .../DisableAnimationAttribute.cs | 1 + .../ReactiveCarouselPage.cs | 2 +- .../ReactiveContentPage.cs | 2 +- .../ReactiveContentView.cs | 2 +- .../ReactiveMasterDetailPage.cs | 2 +- src/ReactiveUI.XamForms/ReactiveMultiPage.cs | 2 +- .../ReactiveNavigationPage.cs | 2 +- src/ReactiveUI.XamForms/ReactiveTabbedPage.cs | 2 +- src/ReactiveUI.XamForms/RoutedViewHost.cs | 2 + src/ReactiveUI.XamForms/ViewModelViewHost.cs | 10 +- src/ReactiveUI.sln | 4 +- .../Activation/ViewModelActivator.cs | 5 + .../Bindings/Command/RelayCommand.cs | 3 + .../Bindings/Reactive/IReactiveBinding.cs | 28 +- .../Bindings/Reactive/ReactiveBinding.cs | 50 +- src/ReactiveUI/Comparers/OrderedComparer.cs | 4 +- .../EventHandlers/LocalizableAttribute.cs | 8 +- .../PropertyChangingEventHandler.cs | 12 +- .../Expression/ExpressionRewriter.cs | 3 + src/ReactiveUI/Interactions/Interaction.cs | 2 +- .../Interfaces/IHandleObservableErrors.cs | 2 +- src/ReactiveUI/Interfaces/IObservedChange.cs | 6 +- .../Interfaces/IPlatformOperations.cs | 2 +- .../IReactiveNotifyPropertyChanged.cs | 4 +- .../IReactivePropertyChangedEventArgs.cs | 4 +- .../Interfaces/IRoutableViewModel.cs | 4 +- src/ReactiveUI/Interfaces/IScreen.cs | 2 +- src/ReactiveUI/Interfaces/ISuspensionHost.cs | 14 +- .../ReactivePropertyChangedEventArgs.cs | 2 +- .../ReactivePropertyChangingEventArgs.cs | 2 +- src/ReactiveUI/Legacy/IReactiveList.cs | 37 +- .../IReactiveNotifyCollectionChanged.cs | 27 +- .../IReactiveNotifyCollectionItemChanged.cs | 9 +- .../Legacy/IReadOnlyReactiveList.cs | 5 +- src/ReactiveUI/Legacy/MoveInfo.cs | 4 + .../Legacy/ReactiveDerivedCollection.cs | 1 + src/ReactiveUI/Legacy/ReactiveList.cs | 2 +- .../Mixins/DependencyResolverMixins.cs | 16 +- .../ObservableAsPropertyHelper.cs | 6 +- .../android/AndroidCommandBinders.cs | 10 +- .../android/AndroidObservableForWidgets.cs | 18 +- .../Platforms/android/AutoSuspendHelper.cs | 59 +- .../Platforms/android/ContextExtensions.cs | 20 +- .../Platforms/android/ControlFetcherMixin.cs | 64 +- .../android/FlexibleCommandBinder.cs | 46 +- ...roidUIScheduler.cs => HandlerScheduler.cs} | 24 +- .../Platforms/android/ILayoutViewHost.cs | 22 + .../android/IgnoreResourceAttribute.cs | 12 + .../Platforms/android/JavaHolder.cs | 20 + .../Platforms/android/LayoutViewHost.cs | 239 +------ .../Platforms/android/ObjectExtension.cs | 14 +- .../Platforms/android/ReactiveActivity.cs | 188 ++--- .../Platforms/android/ReactiveFragment.cs | 56 +- .../Platforms/android/ReactiveListAdapter.cs | 24 +- .../android/ReactivePreferenceActivity.cs | 172 ++--- .../android/ReactivePreferenceFragment.cs | 85 +-- .../Platforms/android/ReactiveViewHost.cs | 152 ++++ .../Platforms/android/ResolveStrategy.cs | 3 + .../Platforms/android/UsbManagerExtensions.cs | 10 +- .../Platforms/android/ViewMixins.cs | 52 ++ .../android/WireUpResourceAttribute.cs | 32 + ...r.cs => AppSupportJsonSuspensionDriver.cs} | 2 +- .../AutoLayoutViewModelViewHost.cs | 33 - .../apple-common/BlockObserveValueDelegate.cs | 31 + ...onverter.cs => DateTimeNSDateConverter.cs} | 5 +- .../Platforms/apple-common/IndexNormalizer.cs | 6 +- .../apple-common/KVOObservableForProperty.cs | 20 +- .../apple-common/ObservableForPropertyBase.cs | 26 +- .../Platforms/apple-common/ReactiveControl.cs | 90 +-- .../apple-common/ReactiveImageView.cs | 30 +- .../ReactiveSplitViewController.cs | 26 +- .../{ReactiveNSView.cs => ReactiveView.cs} | 14 +- ...ontroller.cs => ReactiveViewController.cs} | 40 +- .../apple-common/TargetActionCommandBinder.cs | 22 +- .../apple-common/UIViewControllerMixins.cs | 45 ++ .../Platforms/apple-common/Update.cs | 70 +- .../apple-common/ViewModelViewHost.cs | 248 ++----- .../Platforms/ios/UIKitCommandBinders.cs | 10 +- .../ios/UIKitObservableForProperty.cs | 10 +- .../mac/AppKitObservableForProperty.cs | 10 +- ...oSuspendHelper.cs => AutoSuspendHelper.cs} | 40 +- .../Platforms/mac/ReactiveWindowController.cs | 20 +- .../Platforms/tizen/EcoreMainloopScheduler.cs | 2 +- .../Platforms/tvos/UIKitCommandBinders.cs | 10 +- .../tvos/UIKitObservableForProperty.cs | 10 +- ...endApplication.cs => AutoSuspendHelper.cs} | 36 +- .../DependencyObjectObservableForProperty.cs | 79 +- .../uikit-common/AutoSuspendHelper.cs | 36 +- .../CollectionViewSectionInformation.cs | 3 + .../uikit-common/CommonReactiveSource.cs | 673 +++++++----------- .../uikit-common/FlexibleCommandBinder.cs | 43 +- .../uikit-common/ISectionInformation.cs | 35 + .../uikit-common/IUICollViewAdapter.cs | 103 +++ .../ReactiveCollectionReusableView.cs | 26 +- .../uikit-common/ReactiveCollectionView.cs | 25 +- .../ReactiveCollectionViewCell.cs | 25 +- .../ReactiveCollectionViewController.cs | 24 +- .../ReactiveCollectionViewSource.cs | 286 +------- .../ReactiveCollectionViewSourceExtensions.cs | 112 +++ .../ReactiveNavigationController.cs | 28 +- .../ReactivePageViewController.cs | 30 +- .../uikit-common/ReactiveTabBarController.cs | 26 +- .../uikit-common/ReactiveTableView.cs | 14 +- .../uikit-common/ReactiveTableViewCell.cs | 27 +- .../ReactiveTableViewController.cs | 27 +- .../uikit-common/ReactiveTableViewSource.cs | 232 ++---- .../ReactiveTableViewSourceExtensions.cs | 4 +- .../Platforms/uikit-common/RoutedViewHost.cs | 148 +--- .../uikit-common/SectionInfoIdGenerator.cs | 16 + .../uikit-common/TableSectionHeader.cs | 37 +- .../uikit-common/TableSectionInformation.cs | 3 + .../uikit-common/UICollectionViewAdapter.cs | 143 ++++ .../uikit-common/UITableViewAdapter.cs | 162 +++++ .../AutoDataTemplateBindingHook.cs | 11 +- .../windows-common/BooleanToVisibilityHint.cs | 35 + ...cs => BooleanToVisibilityTypeConverter.cs} | 24 - .../windows-common/ReactiveUserControl.cs | 10 +- .../windows-common/RoutedViewHost.cs | 80 +-- .../windows-common/ViewModelViewHost.cs | 33 +- .../ReactiveCommand/IReactiveCommand.cs | 2 +- .../ReactiveCommand/ReactiveCommand.cs | 3 + .../ReactiveCommand/ReactiveCommandBase.cs | 8 +- .../ReactiveObject/ReactiveObject.cs | 9 +- src/ReactiveUI/Routing/RoutingState.cs | 10 +- src/ReactiveUI/RxApp.cs | 10 +- src/ReactiveUI/View/DefaultViewLocator.cs | 6 + src/reactiveui.ruleset | 162 +++-- src/reactiveui.tests.ruleset | 224 +++--- 190 files changed, 3706 insertions(+), 3542 deletions(-) create mode 100644 src/ApiGeneratorGlobalSuppressions.cs create mode 100644 src/ReactiveUI.AndroidSupport/ReactiveRecyclerViewViewHolder.cs rename src/ReactiveUI.Fody.Tests/API/{ApiApprovalTests.ReactiveUI_Fody.approved.txt => ApiApprovalTests.ReactiveUIFody.approved.txt} (94%) create mode 100644 src/ReactiveUI.Fody.Tests/FodyWeavers.xsd rename src/ReactiveUI.Winforms/{CreatesCommandBinding.cs => CreatesWinformsCommandBinding.cs} (100%) mode change 100755 => 100644 create mode 100644 src/ReactiveUI.Winforms/EventShims/PropertyChangedEventManager.cs create mode 100644 src/ReactiveUI.Winforms/EventShims/PropertyChangingEventManager.cs create mode 100644 src/ReactiveUI.Winforms/IReactiveDerivedBindingList.cs rename src/ReactiveUI.Winforms/{ReactiveDerivedBindingListMixins.cs => ObservableCollectionMixin.cs} (64%) create mode 100644 src/ReactiveUI.Winforms/ReactiveDerivedBindingList.cs delete mode 100644 src/ReactiveUI.Winforms/WeakEventManagerShims.cs rename src/ReactiveUI.Wpf/{WpfAutoSuspendHelper.cs => AutoSuspendHelper.cs} (100%) rename src/ReactiveUI.Wpf/{WpfDependencyObjectObservableForProperty.cs => DependencyObjectObservableForProperty.cs} (96%) rename src/ReactiveUI/Platforms/android/{AndroidUIScheduler.cs => HandlerScheduler.cs} (86%) create mode 100644 src/ReactiveUI/Platforms/android/ILayoutViewHost.cs create mode 100644 src/ReactiveUI/Platforms/android/IgnoreResourceAttribute.cs create mode 100644 src/ReactiveUI/Platforms/android/JavaHolder.cs create mode 100644 src/ReactiveUI/Platforms/android/ReactiveViewHost.cs create mode 100644 src/ReactiveUI/Platforms/android/ViewMixins.cs create mode 100644 src/ReactiveUI/Platforms/android/WireUpResourceAttribute.cs rename src/ReactiveUI/Platforms/apple-common/{JsonSuspensionDriver.cs => AppSupportJsonSuspensionDriver.cs} (96%) delete mode 100644 src/ReactiveUI/Platforms/apple-common/AutoLayoutViewModelViewHost.cs create mode 100644 src/ReactiveUI/Platforms/apple-common/BlockObserveValueDelegate.cs rename src/ReactiveUI/Platforms/apple-common/Converters/{DateTimeToNSDateConverter.cs => DateTimeNSDateConverter.cs} (87%) rename src/ReactiveUI/Platforms/apple-common/{ReactiveNSView.cs => ReactiveView.cs} (91%) rename src/ReactiveUI/Platforms/apple-common/{ReactiveNSViewController.cs => ReactiveViewController.cs} (87%) create mode 100644 src/ReactiveUI/Platforms/apple-common/UIViewControllerMixins.cs rename src/ReactiveUI/Platforms/mac/{AppKitAutoSuspendHelper.cs => AutoSuspendHelper.cs} (73%) rename src/ReactiveUI/Platforms/uap10.0.16299/{WinRTAutoSuspendApplication.cs => AutoSuspendHelper.cs} (75%) create mode 100644 src/ReactiveUI/Platforms/uikit-common/ISectionInformation.cs create mode 100644 src/ReactiveUI/Platforms/uikit-common/IUICollViewAdapter.cs create mode 100644 src/ReactiveUI/Platforms/uikit-common/ReactiveCollectionViewSourceExtensions.cs create mode 100644 src/ReactiveUI/Platforms/uikit-common/SectionInfoIdGenerator.cs create mode 100644 src/ReactiveUI/Platforms/uikit-common/UICollectionViewAdapter.cs create mode 100644 src/ReactiveUI/Platforms/uikit-common/UITableViewAdapter.cs create mode 100644 src/ReactiveUI/Platforms/windows-common/BooleanToVisibilityHint.cs rename src/ReactiveUI/Platforms/windows-common/{BindingTypeConverters.cs => BooleanToVisibilityTypeConverter.cs} (74%) diff --git a/integrationtests/Directory.Build.props b/integrationtests/Directory.Build.props index 64014e66..14a0ee95 100644 --- a/integrationtests/Directory.Build.props +++ b/integrationtests/Directory.Build.props @@ -1,7 +1,6 @@ Copyright (c) .NET Foundation and Contributors - https://opensource.org/licenses/mit https://reactiveui.net https://i.imgur.com/7WDbqSy.png .NET Foundation and Contributors diff --git a/src/ApiGeneratorGlobalSuppressions.cs b/src/ApiGeneratorGlobalSuppressions.cs new file mode 100644 index 00000000..a12ba4d7 --- /dev/null +++ b/src/ApiGeneratorGlobalSuppressions.cs @@ -0,0 +1,161 @@ +// This file is used by Code Analysis to maintain SuppressMessage +// attributes that are applied to this project. +// Project-level suppressions either have no target or are given +// a specific target and scoped to a namespace, type, member, etc. + +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.LayoutRules", "SA1503:Braces should not be omitted", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.AddCtorToTypeDeclaration(System.CodeDom.CodeTypeDeclaration,Mono.Cecil.MethodDefinition,System.Collections.Generic.HashSet{System.String})")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.LayoutRules", "SA1503:Braces should not be omitted", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.AddFieldToTypeDeclaration(System.CodeDom.CodeTypeDeclaration,Mono.Cecil.FieldDefinition,System.Collections.Generic.HashSet{System.String})")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.LayoutRules", "SA1503:Braces should not be omitted", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.AddMemberToTypeDeclaration(System.CodeDom.CodeTypeDeclaration,Mono.Cecil.IMemberDefinition,System.Collections.Generic.HashSet{System.String})")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.LayoutRules", "SA1503:Braces should not be omitted", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.AddMethodToTypeDeclaration(System.CodeDom.CodeTypeDeclaration,Mono.Cecil.MethodDefinition,System.Collections.Generic.HashSet{System.String})")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.LayoutRules", "SA1503:Braces should not be omitted", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.AddPropertyToTypeDeclaration(System.CodeDom.CodeTypeDeclaration,Mono.Cecil.PropertyDefinition,System.Collections.Generic.HashSet{System.String})")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.LayoutRules", "SA1503:Braces should not be omitted", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.CreateDelegateDeclaration(Mono.Cecil.TypeDefinition,System.Collections.Generic.HashSet{System.String})~System.CodeDom.CodeTypeDeclaration")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.LayoutRules", "SA1503:Braces should not be omitted", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.CreateGenericArguments(Mono.Cecil.TypeReference)~System.CodeDom.CodeTypeReference[]")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.LayoutRules", "SA1503:Braces should not be omitted", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.CreateTypeDeclaration(Mono.Cecil.TypeDefinition,System.String[],System.Collections.Generic.HashSet{System.String})~System.CodeDom.CodeTypeDeclaration")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.LayoutRules", "SA1503:Braces should not be omitted", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.GetBaseTypes(Mono.Cecil.TypeDefinition)~System.Collections.Generic.IEnumerable{Mono.Cecil.TypeDefinition}")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.LayoutRules", "SA1503:Braces should not be omitted", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.GetMethodAttributes(Mono.Cecil.MethodDefinition)~System.CodeDom.MemberAttributes")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.LayoutRules", "SA1503:Braces should not be omitted", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.GetPropertyAttributes(System.CodeDom.MemberAttributes,System.CodeDom.MemberAttributes)~System.CodeDom.MemberAttributes")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.LayoutRules", "SA1503:Braces should not be omitted", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.GetTypeName(Mono.Cecil.TypeReference)~System.String")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.LayoutRules", "SA1503:Braces should not be omitted", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.IsDotNetTypeMember(Mono.Cecil.IMemberDefinition,System.String[])~System.Boolean")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.LayoutRules", "SA1503:Braces should not be omitted", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.ModifyCodeTypeReference(System.CodeDom.CodeTypeReference,System.String)~System.CodeDom.CodeTypeReference")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.LayoutRules", "SA1503:Braces should not be omitted", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.PopulateGenericParameters(Mono.Cecil.IGenericParameterProvider,System.CodeDom.CodeTypeParameterCollection)")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.LayoutRules", "SA1503:Braces should not be omitted", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.PopulateMethodParameters(Mono.Cecil.IMethodSignature,System.CodeDom.CodeParameterDeclarationExpressionCollection,System.Collections.Generic.HashSet{System.String},System.Boolean)")] + +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1400:Access modifier should be declared", Justification = "NuGet Inclusion", Scope = "member", Target = "~F:PublicApiGenerator.ApiGenerator.defaultWhitelistedNamespacePrefixes")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Readability", "RCS1018:Add default access modifier.", Justification = "NuGet Inclusion", Scope = "member", Target = "~F:PublicApiGenerator.ApiGenerator.defaultWhitelistedNamespacePrefixes")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1400:Access modifier should be declared", Justification = "NuGet Inclusion", Scope = "member", Target = "~F:PublicApiGenerator.ApiGenerator.OperatorNameMap")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Readability", "RCS1018:Add default access modifier.", Justification = "NuGet Inclusion", Scope = "member", Target = "~F:PublicApiGenerator.ApiGenerator.OperatorNameMap")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1400:Access modifier should be declared", Justification = "NuGet Inclusion", Scope = "member", Target = "~F:PublicApiGenerator.ApiGenerator.SkipAttributeNames")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Readability", "RCS1018:Add default access modifier.", Justification = "NuGet Inclusion", Scope = "member", Target = "~F:PublicApiGenerator.ApiGenerator.SkipAttributeNames")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1400:Access modifier should be declared", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.AddCtorToTypeDeclaration(System.CodeDom.CodeTypeDeclaration,Mono.Cecil.MethodDefinition,System.Collections.Generic.HashSet{System.String})")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Readability", "RCS1018:Add default access modifier.", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.AddCtorToTypeDeclaration(System.CodeDom.CodeTypeDeclaration,Mono.Cecil.MethodDefinition,System.Collections.Generic.HashSet{System.String})")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1400:Access modifier should be declared", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.AddFieldToTypeDeclaration(System.CodeDom.CodeTypeDeclaration,Mono.Cecil.FieldDefinition,System.Collections.Generic.HashSet{System.String})")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Readability", "RCS1018:Add default access modifier.", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.AddFieldToTypeDeclaration(System.CodeDom.CodeTypeDeclaration,Mono.Cecil.FieldDefinition,System.Collections.Generic.HashSet{System.String})")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1400:Access modifier should be declared", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.AddMemberToTypeDeclaration(System.CodeDom.CodeTypeDeclaration,Mono.Cecil.IMemberDefinition,System.Collections.Generic.HashSet{System.String})")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Readability", "RCS1018:Add default access modifier.", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.AddMemberToTypeDeclaration(System.CodeDom.CodeTypeDeclaration,Mono.Cecil.IMemberDefinition,System.Collections.Generic.HashSet{System.String})")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1400:Access modifier should be declared", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.AddMethodToTypeDeclaration(System.CodeDom.CodeTypeDeclaration,Mono.Cecil.MethodDefinition,System.Collections.Generic.HashSet{System.String})")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Readability", "RCS1018:Add default access modifier.", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.AddMethodToTypeDeclaration(System.CodeDom.CodeTypeDeclaration,Mono.Cecil.MethodDefinition,System.Collections.Generic.HashSet{System.String})")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1400:Access modifier should be declared", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.AddPropertyToTypeDeclaration(System.CodeDom.CodeTypeDeclaration,Mono.Cecil.PropertyDefinition,System.Collections.Generic.HashSet{System.String})")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Readability", "RCS1018:Add default access modifier.", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.AddPropertyToTypeDeclaration(System.CodeDom.CodeTypeDeclaration,Mono.Cecil.PropertyDefinition,System.Collections.Generic.HashSet{System.String})")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1400:Access modifier should be declared", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.ConvertAttributeToCode(System.Func{System.CodeDom.CodeTypeReference,System.CodeDom.CodeTypeReference},Mono.Cecil.CustomAttribute)~System.Object")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Readability", "RCS1018:Add default access modifier.", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.ConvertAttributeToCode(System.Func{System.CodeDom.CodeTypeReference,System.CodeDom.CodeTypeReference},Mono.Cecil.CustomAttribute)~System.Object")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1400:Access modifier should be declared", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.CreateCodeTypeReference(Mono.Cecil.TypeReference)~System.CodeDom.CodeTypeReference")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Readability", "RCS1018:Add default access modifier.", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.CreateCodeTypeReference(Mono.Cecil.TypeReference)~System.CodeDom.CodeTypeReference")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1400:Access modifier should be declared", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.CreateCustomAttributes(Mono.Cecil.ICustomAttributeProvider,System.Collections.Generic.HashSet{System.String})~System.CodeDom.CodeAttributeDeclarationCollection")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Readability", "RCS1018:Add default access modifier.", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.CreateCustomAttributes(Mono.Cecil.ICustomAttributeProvider,System.Collections.Generic.HashSet{System.String})~System.CodeDom.CodeAttributeDeclarationCollection")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1400:Access modifier should be declared", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.CreateDelegateDeclaration(Mono.Cecil.TypeDefinition,System.Collections.Generic.HashSet{System.String})~System.CodeDom.CodeTypeDeclaration")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Readability", "RCS1018:Add default access modifier.", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.CreateDelegateDeclaration(Mono.Cecil.TypeDefinition,System.Collections.Generic.HashSet{System.String})~System.CodeDom.CodeTypeDeclaration")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1400:Access modifier should be declared", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.CreateGenericArguments(Mono.Cecil.TypeReference)~System.CodeDom.CodeTypeReference[]")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Readability", "RCS1018:Add default access modifier.", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.CreateGenericArguments(Mono.Cecil.TypeReference)~System.CodeDom.CodeTypeReference[]")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1400:Access modifier should be declared", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.CreateInitialiserExpression(Mono.Cecil.CustomAttributeArgument)~System.CodeDom.CodeExpression")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Readability", "RCS1018:Add default access modifier.", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.CreateInitialiserExpression(Mono.Cecil.CustomAttributeArgument)~System.CodeDom.CodeExpression")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1400:Access modifier should be declared", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.CreatePublicApiForAssembly(Mono.Cecil.AssemblyDefinition,System.Func{Mono.Cecil.TypeDefinition,System.Boolean},System.Boolean,System.String[],System.Collections.Generic.HashSet{System.String})~System.String")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Readability", "RCS1018:Add default access modifier.", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.CreatePublicApiForAssembly(Mono.Cecil.AssemblyDefinition,System.Func{Mono.Cecil.TypeDefinition,System.Boolean},System.Boolean,System.String[],System.Collections.Generic.HashSet{System.String})~System.String")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1400:Access modifier should be declared", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.CreateTypeDeclaration(Mono.Cecil.TypeDefinition,System.String[],System.Collections.Generic.HashSet{System.String})~System.CodeDom.CodeTypeDeclaration")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Readability", "RCS1018:Add default access modifier.", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.CreateTypeDeclaration(Mono.Cecil.TypeDefinition,System.String[],System.Collections.Generic.HashSet{System.String})~System.CodeDom.CodeTypeDeclaration")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1400:Access modifier should be declared", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.FormatParameterConstant(Mono.Cecil.IConstantProvider)~System.Object")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Readability", "RCS1018:Add default access modifier.", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.FormatParameterConstant(Mono.Cecil.IConstantProvider)~System.Object")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1400:Access modifier should be declared", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.GenerateCodeAttributeDeclaration(System.Func{System.CodeDom.CodeTypeReference,System.CodeDom.CodeTypeReference},Mono.Cecil.CustomAttribute)~System.CodeDom.CodeAttributeDeclaration")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Readability", "RCS1018:Add default access modifier.", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.GenerateCodeAttributeDeclaration(System.Func{System.CodeDom.CodeTypeReference,System.CodeDom.CodeTypeReference},Mono.Cecil.CustomAttribute)~System.CodeDom.CodeAttributeDeclaration")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1400:Access modifier should be declared", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.GenerateEvent(Mono.Cecil.EventDefinition,System.Collections.Generic.HashSet{System.String})~System.CodeDom.CodeTypeMember")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Readability", "RCS1018:Add default access modifier.", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.GenerateEvent(Mono.Cecil.EventDefinition,System.Collections.Generic.HashSet{System.String})~System.CodeDom.CodeTypeMember")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1400:Access modifier should be declared", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.GetBaseTypes(Mono.Cecil.TypeDefinition)~System.Collections.Generic.IEnumerable{Mono.Cecil.TypeDefinition}")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Readability", "RCS1018:Add default access modifier.", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.GetBaseTypes(Mono.Cecil.TypeDefinition)~System.Collections.Generic.IEnumerable{Mono.Cecil.TypeDefinition}")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1400:Access modifier should be declared", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.GetMethodAttributes(Mono.Cecil.MethodDefinition)~System.CodeDom.MemberAttributes")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Readability", "RCS1018:Add default access modifier.", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.GetMethodAttributes(Mono.Cecil.MethodDefinition)~System.CodeDom.MemberAttributes")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1400:Access modifier should be declared", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.GetPropertyAttributes(System.CodeDom.MemberAttributes,System.CodeDom.MemberAttributes)~System.CodeDom.MemberAttributes")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Readability", "RCS1018:Add default access modifier.", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.GetPropertyAttributes(System.CodeDom.MemberAttributes,System.CodeDom.MemberAttributes)~System.CodeDom.MemberAttributes")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1400:Access modifier should be declared", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.GetTypeName(Mono.Cecil.TypeReference)~System.String")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Readability", "RCS1018:Add default access modifier.", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.GetTypeName(Mono.Cecil.TypeReference)~System.String")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1400:Access modifier should be declared", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.HasVisiblePropertyMethod(System.CodeDom.MemberAttributes)~System.Boolean")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Readability", "RCS1018:Add default access modifier.", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.HasVisiblePropertyMethod(System.CodeDom.MemberAttributes)~System.Boolean")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1400:Access modifier should be declared", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.IsCompilerGenerated(Mono.Cecil.IMemberDefinition)~System.Boolean")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Readability", "RCS1018:Add default access modifier.", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.IsCompilerGenerated(Mono.Cecil.IMemberDefinition)~System.Boolean")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1400:Access modifier should be declared", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.IsDelegate(Mono.Cecil.TypeDefinition)~System.Boolean")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Readability", "RCS1018:Add default access modifier.", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.IsDelegate(Mono.Cecil.TypeDefinition)~System.Boolean")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1400:Access modifier should be declared", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.IsDotNetTypeMember(Mono.Cecil.IMemberDefinition,System.String[])~System.Boolean")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Readability", "RCS1018:Add default access modifier.", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.IsDotNetTypeMember(Mono.Cecil.IMemberDefinition,System.String[])~System.Boolean")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1400:Access modifier should be declared", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.IsExtensionMethod(Mono.Cecil.ICustomAttributeProvider)~System.Boolean")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Readability", "RCS1018:Add default access modifier.", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.IsExtensionMethod(Mono.Cecil.ICustomAttributeProvider)~System.Boolean")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1400:Access modifier should be declared", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.IsHidingMethod(Mono.Cecil.MethodDefinition)~System.Boolean")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Readability", "RCS1018:Add default access modifier.", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.IsHidingMethod(Mono.Cecil.MethodDefinition)~System.Boolean")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1400:Access modifier should be declared", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.MakeReadonly(System.CodeDom.CodeTypeReference)~System.CodeDom.CodeTypeReference")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Readability", "RCS1018:Add default access modifier.", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.MakeReadonly(System.CodeDom.CodeTypeReference)~System.CodeDom.CodeTypeReference")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1400:Access modifier should be declared", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.ModifyCodeTypeReference(System.CodeDom.CodeTypeReference,System.String)~System.CodeDom.CodeTypeReference")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Readability", "RCS1018:Add default access modifier.", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.ModifyCodeTypeReference(System.CodeDom.CodeTypeReference,System.String)~System.CodeDom.CodeTypeReference")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1400:Access modifier should be declared", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.NormaliseGeneratedCode(System.IO.StringWriter)~System.String")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Readability", "RCS1018:Add default access modifier.", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.NormaliseGeneratedCode(System.IO.StringWriter)~System.String")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1400:Access modifier should be declared", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.NormaliseLineEndings(System.String)~System.String")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Readability", "RCS1018:Add default access modifier.", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.NormaliseLineEndings(System.String)~System.String")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1400:Access modifier should be declared", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.PopulateCustomAttributes(Mono.Cecil.ICustomAttributeProvider,System.CodeDom.CodeAttributeDeclarationCollection,System.Collections.Generic.HashSet{System.String})")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Readability", "RCS1018:Add default access modifier.", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.PopulateCustomAttributes(Mono.Cecil.ICustomAttributeProvider,System.CodeDom.CodeAttributeDeclarationCollection,System.Collections.Generic.HashSet{System.String})")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1400:Access modifier should be declared", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.PopulateCustomAttributes(Mono.Cecil.ICustomAttributeProvider,System.CodeDom.CodeAttributeDeclarationCollection,System.Func{System.CodeDom.CodeTypeReference,System.CodeDom.CodeTypeReference},System.Collections.Generic.HashSet{System.String})")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Readability", "RCS1018:Add default access modifier.", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.PopulateCustomAttributes(Mono.Cecil.ICustomAttributeProvider,System.CodeDom.CodeAttributeDeclarationCollection,System.Func{System.CodeDom.CodeTypeReference,System.CodeDom.CodeTypeReference},System.Collections.Generic.HashSet{System.String})")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1400:Access modifier should be declared", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.PopulateGenericParameters(Mono.Cecil.IGenericParameterProvider,System.CodeDom.CodeTypeParameterCollection)")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Readability", "RCS1018:Add default access modifier.", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.PopulateGenericParameters(Mono.Cecil.IGenericParameterProvider,System.CodeDom.CodeTypeParameterCollection)")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1400:Access modifier should be declared", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.PopulateMethodParameters(Mono.Cecil.IMethodSignature,System.CodeDom.CodeParameterDeclarationExpressionCollection,System.Collections.Generic.HashSet{System.String},System.Boolean)")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Readability", "RCS1018:Add default access modifier.", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.PopulateMethodParameters(Mono.Cecil.IMethodSignature,System.CodeDom.CodeParameterDeclarationExpressionCollection,System.Collections.Generic.HashSet{System.String},System.Boolean)")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1400:Access modifier should be declared", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.RemoveUnnecessaryWhiteSpace(System.String)~System.String")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Readability", "RCS1018:Add default access modifier.", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.RemoveUnnecessaryWhiteSpace(System.String)~System.String")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1400:Access modifier should be declared", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.ShouldIncludeAttribute(Mono.Cecil.CustomAttribute,System.Collections.Generic.HashSet{System.String})~System.Boolean")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Readability", "RCS1018:Add default access modifier.", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.ShouldIncludeAttribute(Mono.Cecil.CustomAttribute,System.Collections.Generic.HashSet{System.String})~System.Boolean")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1400:Access modifier should be declared", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.ShouldIncludeMember(Mono.Cecil.IMemberDefinition,System.String[])~System.Boolean")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Readability", "RCS1018:Add default access modifier.", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.ShouldIncludeMember(Mono.Cecil.IMemberDefinition,System.String[])~System.Boolean")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1400:Access modifier should be declared", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.ShouldIncludeType(Mono.Cecil.TypeDefinition)~System.Boolean")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Readability", "RCS1018:Add default access modifier.", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.ShouldIncludeType(Mono.Cecil.TypeDefinition)~System.Boolean")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1400:Access modifier should be declared", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.ShouldOutputBaseType(Mono.Cecil.TypeDefinition)~System.Boolean")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Readability", "RCS1018:Add default access modifier.", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.ShouldOutputBaseType(Mono.Cecil.TypeDefinition)~System.Boolean")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1400:Access modifier should be declared", Justification = "NuGet Inclusion", Scope = "type", Target = "~T:PublicApiGenerator.CecilEx")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Readability", "RCS1018:Add default access modifier.", Justification = "NuGet Inclusion", Scope = "type", Target = "~T:PublicApiGenerator.CecilEx")] + +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.SpacingRules", "SA1009:Closing parenthesis should be spaced correctly", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.AddMemberToTypeDeclaration(System.CodeDom.CodeTypeDeclaration,Mono.Cecil.IMemberDefinition,System.Collections.Generic.HashSet{System.String})")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.SpacingRules", "SA1003:Symbols should be spaced correctly", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.AddMemberToTypeDeclaration(System.CodeDom.CodeTypeDeclaration,Mono.Cecil.IMemberDefinition,System.Collections.Generic.HashSet{System.String})")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.SpacingRules", "SA1009:Closing parenthesis should be spaced correctly", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.CreateInitialiserExpression(Mono.Cecil.CustomAttributeArgument)~System.CodeDom.CodeExpression")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.SpacingRules", "SA1003:Symbols should be spaced correctly", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.CreateInitialiserExpression(Mono.Cecil.CustomAttributeArgument)~System.CodeDom.CodeExpression")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.SpacingRules", "SA1009:Closing parenthesis should be spaced correctly", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.GetPropertyAttributes(System.CodeDom.MemberAttributes,System.CodeDom.MemberAttributes)~System.CodeDom.MemberAttributes")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.SpacingRules", "SA1003:Symbols should be spaced correctly", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.GetPropertyAttributes(System.CodeDom.MemberAttributes,System.CodeDom.MemberAttributes)~System.CodeDom.MemberAttributes")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.SpacingRules", "SA1009:Closing parenthesis should be spaced correctly", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.RemoveUnnecessaryWhiteSpace(System.String)~System.String")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.ReadabilityRules", "SA1122:Use string.Empty for empty strings", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.GetTypeName(Mono.Cecil.TypeReference)~System.String")] + +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Globalization", "CA1305:Specify IFormatProvider", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.CreateInitialiserExpression(Mono.Cecil.CustomAttributeArgument)~System.CodeDom.CodeExpression")] + +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.LayoutRules", "SA1513:Closing brace should be followed by blank line", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.AddPropertyToTypeDeclaration(System.CodeDom.CodeTypeDeclaration,Mono.Cecil.PropertyDefinition,System.Collections.Generic.HashSet{System.String})")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.LayoutRules", "SA1513:Closing brace should be followed by blank line", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.CreateGenericArguments(Mono.Cecil.TypeReference)~System.CodeDom.CodeTypeReference[]")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.LayoutRules", "SA1513:Closing brace should be followed by blank line", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.CreatePublicApiForAssembly(Mono.Cecil.AssemblyDefinition,System.Func{Mono.Cecil.TypeDefinition,System.Boolean},System.Boolean,System.String[],System.Collections.Generic.HashSet{System.String})~System.String")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.LayoutRules", "SA1513:Closing brace should be followed by blank line", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.CreateTypeDeclaration(Mono.Cecil.TypeDefinition,System.String[],System.Collections.Generic.HashSet{System.String})~System.CodeDom.CodeTypeDeclaration")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.LayoutRules", "SA1513:Closing brace should be followed by blank line", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.GenerateCodeAttributeDeclaration(System.Func{System.CodeDom.CodeTypeReference,System.CodeDom.CodeTypeReference},Mono.Cecil.CustomAttribute)~System.CodeDom.CodeAttributeDeclaration")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.LayoutRules", "SA1513:Closing brace should be followed by blank line", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.PopulateGenericParameters(Mono.Cecil.IGenericParameterProvider,System.CodeDom.CodeTypeParameterCollection)")] + +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "RCS1001:Add braces (when expression spans over multiple lines).", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.CreateTypeDeclaration(Mono.Cecil.TypeDefinition,System.String[],System.Collections.Generic.HashSet{System.String})~System.CodeDom.CodeTypeDeclaration")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.ReadabilityRules", "SA1117:Parameters should be on same line or separate lines", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.GeneratePublicApi(System.Reflection.Assembly,System.Type[],System.Boolean,System.String[],System.String[])~System.String")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.ReadabilityRules", "SA1117:Parameters should be on same line or separate lines", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.NormaliseGeneratedCode(System.IO.StringWriter)~System.String")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.ReadabilityRules", "SA1116:Split parameters should start on line after declaration", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.AddMemberToTypeDeclaration(System.CodeDom.CodeTypeDeclaration,Mono.Cecil.IMemberDefinition,System.Collections.Generic.HashSet{System.String})")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.ReadabilityRules", "SA1116:Split parameters should start on line after declaration", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.AddPropertyToTypeDeclaration(System.CodeDom.CodeTypeDeclaration,Mono.Cecil.PropertyDefinition,System.Collections.Generic.HashSet{System.String})")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.ReadabilityRules", "SA1116:Split parameters should start on line after declaration", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.CreateCustomAttributes(Mono.Cecil.ICustomAttributeProvider,System.Collections.Generic.HashSet{System.String})~System.CodeDom.CodeAttributeDeclarationCollection")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.ReadabilityRules", "SA1116:Split parameters should start on line after declaration", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.PopulateCustomAttributes(Mono.Cecil.ICustomAttributeProvider,System.CodeDom.CodeAttributeDeclarationCollection,System.Collections.Generic.HashSet{System.String})")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.ReadabilityRules", "SA1116:Split parameters should start on line after declaration", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.PopulateCustomAttributes(Mono.Cecil.ICustomAttributeProvider,System.CodeDom.CodeAttributeDeclarationCollection,System.Func{System.CodeDom.CodeTypeReference,System.CodeDom.CodeTypeReference},System.Collections.Generic.HashSet{System.String})")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.ReadabilityRules", "SA1116:Split parameters should start on line after declaration", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.PopulateMethodParameters(Mono.Cecil.IMethodSignature,System.CodeDom.CodeParameterDeclarationExpressionCollection,System.Collections.Generic.HashSet{System.String},System.Boolean)")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.ReadabilityRules", "SA1116:Split parameters should start on line after declaration", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.RemoveUnnecessaryWhiteSpace(System.String)~System.String")] + +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.SpacingRules", "SA1000:Keywords should be spaced correctly", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.CreateTypeDeclaration(Mono.Cecil.TypeDefinition,System.String[],System.Collections.Generic.HashSet{System.String})~System.CodeDom.CodeTypeDeclaration")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.OrderingRules", "SA1209:Using alias directives should be placed after other using directives", Justification = "NuGet Inclusion")] + +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.OrderingRules", "SA1210:Using directives should be ordered alphabetically by namespace", Justification = "NuGet Inclusion")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.OrderingRules", "SA1208:System using directives should be placed before other using directives", Justification = "NuGet Inclusion")] + +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.OrderingRules", "SA1201:Elements should appear in the correct order", Justification = "NuGet Inclusion", Scope = "member", Target = "~F:PublicApiGenerator.ApiGenerator.OperatorNameMap")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.OrderingRules", "SA1201:Elements should appear in the correct order", Justification = "NuGet Inclusion", Scope = "member", Target = "~F:PublicApiGenerator.ApiGenerator.SkipAttributeNames")] + +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Performance", "CA1825:Avoid zero-length array allocations.", Justification = "NuGet Inclusion", Scope = "member", Target = "~F:PublicApiGenerator.ApiGenerator.defaultWhitelistedNamespacePrefixes")] + +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Globalization", "CA1307:Specify StringComparison", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.AddMethodToTypeDeclaration(System.CodeDom.CodeTypeDeclaration,Mono.Cecil.MethodDefinition,System.Collections.Generic.HashSet{System.String})")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Globalization", "CA1307:Specify StringComparison", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.IsDotNetTypeMember(Mono.Cecil.IMemberDefinition,System.String[])~System.Boolean")] + +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.LayoutRules", "SA1512:Single-line comments should not be followed by blank line", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.AddPropertyToTypeDeclaration(System.CodeDom.CodeTypeDeclaration,Mono.Cecil.PropertyDefinition,System.Collections.Generic.HashSet{System.String})")] + +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.LayoutRules", "SA1515:Single-line comment should be preceded by blank line", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.AddMethodToTypeDeclaration(System.CodeDom.CodeTypeDeclaration,Mono.Cecil.MethodDefinition,System.Collections.Generic.HashSet{System.String})")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.LayoutRules", "SA1515:Single-line comment should be preceded by blank line", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.CreateTypeDeclaration(Mono.Cecil.TypeDefinition,System.String[],System.Collections.Generic.HashSet{System.String})~System.CodeDom.CodeTypeDeclaration")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.LayoutRules", "SA1520:Use braces consistently", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.CreateTypeDeclaration(Mono.Cecil.TypeDefinition,System.String[],System.Collections.Generic.HashSet{System.String})~System.CodeDom.CodeTypeDeclaration")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:File may only contain a single type", Justification = "NuGet Inclusion", Scope = "type", Target = "~T:PublicApiGenerator.CecilEx")] + +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.SpacingRules", "SA1005:Single line comments should begin with single space", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.CreateInitialiserExpression(Mono.Cecil.CustomAttributeArgument)~System.CodeDom.CodeExpression")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.ReadabilityRules", "SA1111:Closing parenthesis should be on line of last parameter", Justification = "NuGet Inclusion", Scope = "member", Target = "~M:PublicApiGenerator.ApiGenerator.RemoveUnnecessaryWhiteSpace(System.String)~System.String")] diff --git a/src/Directory.build.props b/src/Directory.build.props index 72bd75df..ed031730 100644 --- a/src/Directory.build.props +++ b/src/Directory.build.props @@ -1,7 +1,6 @@ .NET Foundation and Contributors - $(MSBuildThisFileDirectory)reactiveui.ruleset Copyright (c) .NET Foundation and Contributors https://opensource.org/licenses/mit https://reactiveui.net @@ -13,9 +12,7 @@ https://github.com/reactiveui/reactiveui git true - $(NoWarn);1591;1701;1702;1705;VSX1000 - true AnyCPU $(MSBuildProjectName.Contains('Tests')) @@ -28,15 +25,15 @@ $(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb - + + + $(MSBuildThisFileDirectory)reactiveui.ruleset + + $(MSBuildThisFileDirectory)reactiveui.tests.ruleset false - - - - @@ -48,6 +45,10 @@ + + + + @@ -56,7 +57,11 @@ $(MSBuildThisFileDirectory) - + + + + + diff --git a/src/EventBuilder/DefaultTemplate.mustache b/src/EventBuilder/DefaultTemplate.mustache index 4bf042fd..b7a752e5 100644 --- a/src/EventBuilder/DefaultTemplate.mustache +++ b/src/EventBuilder/DefaultTemplate.mustache @@ -2,6 +2,15 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +//------------------------------------------------------------------------------ +// +// This code was generated from a template. +// +// Manual changes to this file may cause unexpected behavior in your application. +// Manual changes to this file will be overwritten if the code is regenerated. +// +//------------------------------------------------------------------------------ + #pragma warning disable 1591,0618,0105,0672,0108,SA1402,SA1200,SA1514,SA1615,SA1210,SA1001,SA1403,SA1201,SA1306,SA1601,SA1513,SA1004,SA1516,SA1508,SA1629,SA1507,SA1121,SA1208 using System; diff --git a/src/EventBuilder/Platforms/IPlatform.cs b/src/EventBuilder/Platforms/IPlatform.cs index 9c995570..f99b1cf9 100644 --- a/src/EventBuilder/Platforms/IPlatform.cs +++ b/src/EventBuilder/Platforms/IPlatform.cs @@ -17,12 +17,12 @@ namespace EventBuilder.Platforms AutoPlatform Platform { get; } /// - /// Gets or sets the assemblies. + /// Gets the assemblies. /// List Assemblies { get; } /// - /// Gets or sets the cecil search directories. + /// Gets the cecil search directories. /// Cecil when run on Mono needs some direction as to the location of the platform specific MSCORLIB. /// List CecilSearchDirectories { get; } diff --git a/src/EventBuilder/XamarinEssentialsTemplate.mustache b/src/EventBuilder/XamarinEssentialsTemplate.mustache index 0be22be7..5d4e686e 100644 --- a/src/EventBuilder/XamarinEssentialsTemplate.mustache +++ b/src/EventBuilder/XamarinEssentialsTemplate.mustache @@ -1,4 +1,17 @@ -#pragma warning disable 1591,0618,0105,0672,SA1600 +// 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. + +//------------------------------------------------------------------------------ +// +// This code was generated from a template. +// +// Manual changes to this file may cause unexpected behavior in your application. +// Manual changes to this file will be overwritten if the code is regenerated. +// +//------------------------------------------------------------------------------ + +#pragma warning disable 1591,0618,0105,0672,0108,SA1402,SA1200,SA1514,SA1615,SA1210,SA1001,SA1403,SA1201,SA1306,SA1601,SA1513,SA1004,SA1516,SA1508,SA1629,SA1507,SA1121,SA1208 using System; using System.Reactive; diff --git a/src/ReactiveUI.AndroidSupport/ControlFetcherMixin.cs b/src/ReactiveUI.AndroidSupport/ControlFetcherMixin.cs index a29b2db7..b14e441a 100644 --- a/src/ReactiveUI.AndroidSupport/ControlFetcherMixin.cs +++ b/src/ReactiveUI.AndroidSupport/ControlFetcherMixin.cs @@ -72,11 +72,11 @@ namespace ReactiveUI.AndroidSupport /// This should be called in the Fragement's OnCreateView, with the newly inflated layout. /// /// The fragment. - /// The newly inflated returned from . + /// The newly inflated returned from Inflate. /// The strategy used to resolve properties that either subclass , have a or have a . public static void WireUpControls(this Android.Support.V4.App.Fragment @this, View inflatedView, ResolveStrategy resolveMembers = ResolveStrategy.Implicit) { - var members = @this.GetWireUpMembers(ResolveStrategy.Implicit); + var members = @this.GetWireUpMembers(resolveMembers); members.ToList().ForEach(m => { @@ -104,8 +104,7 @@ namespace ReactiveUI.AndroidSupport switch (resolveStrategy) { - default: - case ResolveStrategy.Implicit: + default: // Implicit uses the default case. return members.Where(m => m.PropertyType.IsSubclassOf(typeof(View)) || m.GetCustomAttribute(true) != null); diff --git a/src/ReactiveUI.AndroidSupport/ReactiveAppCompatActivity.cs b/src/ReactiveUI.AndroidSupport/ReactiveAppCompatActivity.cs index d409e28f..329122fa 100644 --- a/src/ReactiveUI.AndroidSupport/ReactiveAppCompatActivity.cs +++ b/src/ReactiveUI.AndroidSupport/ReactiveAppCompatActivity.cs @@ -4,6 +4,7 @@ using System; using System.ComponentModel; +using System.Diagnostics.CodeAnalysis; using System.Reactive; using System.Reactive.Linq; using System.Reactive.Subjects; @@ -21,6 +22,7 @@ namespace ReactiveUI.AndroidSupport /// (i.e. you can call RaiseAndSetIfChanged). /// /// The view model type. + [SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:FileMayOnlyContainASingleType", Justification = "Classes with the same class names within.")] public class ReactiveAppCompatActivity : ReactiveAppCompatActivity, IViewFor, ICanActivate where TViewModel : class { @@ -52,49 +54,13 @@ namespace ReactiveUI.AndroidSupport /// This is an Activity that is both an Activity and has ReactiveObject powers /// (i.e. you can call RaiseAndSetIfChanged). /// + [SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:FileMayOnlyContainASingleType", Justification = "Classes with the same class names within.")] public class ReactiveAppCompatActivity : AppCompatActivity, IReactiveObject, IReactiveNotifyPropertyChanged, IHandleObservableErrors { private readonly Subject _activated = new Subject(); private readonly Subject _deactivated = new Subject(); private readonly Subject> _activityResult = new Subject>(); - /// - public event PropertyChangingEventHandler PropertyChanging - { - add => PropertyChangingEventManager.AddHandler(this, value); - remove => PropertyChangingEventManager.RemoveHandler(this, value); - } - - /// - public event PropertyChangedEventHandler PropertyChanged - { - add => PropertyChangedEventManager.AddHandler(this, value); - remove => PropertyChangedEventManager.RemoveHandler(this, value); - } - - /// - void IReactiveObject.RaisePropertyChanging(PropertyChangingEventArgs args) - { - PropertyChangingEventManager.DeliverEvent(this, args); - } - - /// - void IReactiveObject.RaisePropertyChanged(PropertyChangedEventArgs args) - { - PropertyChangedEventManager.DeliverEvent(this, args); - } - - /// - /// Represents an Observable that fires *before* a property is about to - /// be changed. - /// - public IObservable> Changing => this.GetChangingObservable(); - - /// - /// Represents an Observable that fires *after* a property has changed. - /// - public IObservable> Changed => this.GetChangedObservable(); - /// /// Initializes a new instance of the class. /// @@ -112,18 +78,26 @@ namespace ReactiveUI.AndroidSupport { } - /// - /// When this method is called, an object will not fire change - /// notifications (neither traditional nor Observable notifications) - /// until the return value is disposed. - /// - /// An object that, when disposed, reenables change - /// notifications. - public IDisposable SuppressChangeNotifications() + /// + public event PropertyChangingEventHandler PropertyChanging { - return IReactiveObjectExtensions.SuppressChangeNotifications(this); + add => PropertyChangingEventManager.AddHandler(this, value); + remove => PropertyChangingEventManager.RemoveHandler(this, value); } + /// + public event PropertyChangedEventHandler PropertyChanged + { + add => PropertyChangedEventManager.AddHandler(this, value); + remove => PropertyChangedEventManager.RemoveHandler(this, value); + } + + /// + public IObservable> Changing => this.GetChangingObservable(); + + /// + public IObservable> Changed => this.GetChangedObservable(); + /// public IObservable ThrownExceptions => this.GetThrownExceptionsObservable(); @@ -151,6 +125,24 @@ namespace ReactiveUI.AndroidSupport /// public IObservable> ActivityResult => _activityResult.AsObservable(); + /// + void IReactiveObject.RaisePropertyChanging(PropertyChangingEventArgs args) + { + PropertyChangingEventManager.DeliverEvent(this, args); + } + + /// + void IReactiveObject.RaisePropertyChanged(PropertyChangedEventArgs args) + { + PropertyChangedEventManager.DeliverEvent(this, args); + } + + /// + public IDisposable SuppressChangeNotifications() + { + return IReactiveObjectExtensions.SuppressChangeNotifications(this); + } + /// /// Starts the activity for result asynchronously. /// diff --git a/src/ReactiveUI.AndroidSupport/ReactiveDialogFragment.cs b/src/ReactiveUI.AndroidSupport/ReactiveDialogFragment.cs index 15b2e14b..bfa8eb05 100644 --- a/src/ReactiveUI.AndroidSupport/ReactiveDialogFragment.cs +++ b/src/ReactiveUI.AndroidSupport/ReactiveDialogFragment.cs @@ -4,6 +4,7 @@ using System; using System.ComponentModel; +using System.Diagnostics.CodeAnalysis; using System.Reactive; using System.Reactive.Linq; using System.Reactive.Subjects; @@ -15,6 +16,7 @@ namespace ReactiveUI.AndroidSupport /// (i.e. you can call RaiseAndSetIfChanged). /// /// The view model type. + [SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:FileMayOnlyContainASingleType", Justification = "Classes with the same class names within.")] public class ReactiveDialogFragment : ReactiveDialogFragment, IViewFor, ICanActivate where TViewModel : class { @@ -46,6 +48,7 @@ namespace ReactiveUI.AndroidSupport /// This is a Fragment that is both an Activity and has ReactiveObject powers /// (i.e. you can call RaiseAndSetIfChanged). /// + [SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:FileMayOnlyContainASingleType", Justification = "Classes with the same class names within.")] public class ReactiveDialogFragment : Android.Support.V4.App.DialogFragment, IReactiveNotifyPropertyChanged, IReactiveObject, IHandleObservableErrors { private readonly Subject _activated = new Subject(); @@ -76,24 +79,19 @@ namespace ReactiveUI.AndroidSupport public IObservable ThrownExceptions => this.GetThrownExceptionsObservable(); /// - /// Gets a signal when the fragment is activated. + /// Gets a observable that signals when the fragment is activated. /// public IObservable Activated => _activated.AsObservable(); /// - /// Gets a signal when the fragment is deactivated. + /// Gets a observable that signals when the fragment is deactivated. /// public IObservable Deactivated => _deactivated.AsObservable(); - /// - /// Represents an Observable that fires *before* a property is about to - /// be changed. - /// + /// public IObservable> Changing => this.GetChangingObservable(); - /// - /// Represents an Observable that fires *after* a property has changed. - /// + /// public IObservable> Changed => this.GetChangedObservable(); /// @@ -108,13 +106,7 @@ namespace ReactiveUI.AndroidSupport PropertyChangedEventManager.DeliverEvent(this, args); } - /// - /// When this method is called, an object will not fire change - /// notifications (neither traditional nor Observable notifications) - /// until the return value is disposed. - /// - /// An object that, when disposed, reenables change - /// notifications. + /// public IDisposable SuppressChangeNotifications() { return IReactiveObjectExtensions.SuppressChangeNotifications(this); diff --git a/src/ReactiveUI.AndroidSupport/ReactiveFragment.cs b/src/ReactiveUI.AndroidSupport/ReactiveFragment.cs index 6942a71c..e4340585 100644 --- a/src/ReactiveUI.AndroidSupport/ReactiveFragment.cs +++ b/src/ReactiveUI.AndroidSupport/ReactiveFragment.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using System.ComponentModel; +using System.Diagnostics.CodeAnalysis; using System.Diagnostics.Contracts; using System.Linq; using System.Reactive; @@ -33,6 +34,7 @@ namespace ReactiveUI.AndroidSupport /// (i.e. you can call RaiseAndSetIfChanged). /// /// The view model type. + [SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:FileMayOnlyContainASingleType", Justification = "Classes with the same class names within.")] public class ReactiveFragment : ReactiveFragment, IViewFor, ICanActivate where TViewModel : class { @@ -64,6 +66,7 @@ namespace ReactiveUI.AndroidSupport /// This is a Fragment that is both an Activity and has ReactiveObject powers /// (i.e. you can call RaiseAndSetIfChanged). /// + [SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:FileMayOnlyContainASingleType", Justification = "Classes with the same class names within.")] public class ReactiveFragment : Android.Support.V4.App.Fragment, IReactiveNotifyPropertyChanged, IReactiveObject, IHandleObservableErrors { private readonly Subject _activated = new Subject(); @@ -103,15 +106,10 @@ namespace ReactiveUI.AndroidSupport /// public IObservable Deactivated => _deactivated.AsObservable(); - /// - /// Represents an Observable that fires *before* a property is about to - /// be changed. - /// + /// public IObservable> Changing => this.GetChangingObservable(); - /// - /// Represents an Observable that fires *after* a property has changed. - /// + /// public IObservable> Changed => this.GetChangedObservable(); /// @@ -126,13 +124,7 @@ namespace ReactiveUI.AndroidSupport PropertyChangedEventManager.DeliverEvent(this, args); } - /// - /// When this method is called, an object will not fire change - /// notifications (neither traditional nor Observable notifications) - /// until the return value is disposed. - /// - /// An object that, when disposed, re-enables change - /// notifications. + /// public IDisposable SuppressChangeNotifications() { return IReactiveObjectExtensions.SuppressChangeNotifications(this); diff --git a/src/ReactiveUI.AndroidSupport/ReactiveFragmentActivity.cs b/src/ReactiveUI.AndroidSupport/ReactiveFragmentActivity.cs index 6cce73e4..5956d606 100644 --- a/src/ReactiveUI.AndroidSupport/ReactiveFragmentActivity.cs +++ b/src/ReactiveUI.AndroidSupport/ReactiveFragmentActivity.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using System.ComponentModel; +using System.Diagnostics.CodeAnalysis; using System.Diagnostics.Contracts; using System.Linq; using System.Reactive; @@ -35,6 +36,7 @@ namespace ReactiveUI.AndroidSupport /// (i.e. you can call RaiseAndSetIfChanged). /// /// The view model type. + [SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:FileMayOnlyContainASingleType", Justification = "Classes with the same class names within.")] public class ReactiveFragmentActivity : ReactiveFragmentActivity, IViewFor, ICanActivate where TViewModel : class { @@ -66,6 +68,7 @@ namespace ReactiveUI.AndroidSupport /// This is an Activity that is both an Activity and has ReactiveObject powers /// (i.e. you can call RaiseAndSetIfChanged). /// + [SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:FileMayOnlyContainASingleType", Justification = "Classes with the same class names within.")] public class ReactiveFragmentActivity : FragmentActivity, IReactiveObject, IReactiveNotifyPropertyChanged, IHandleObservableErrors { private readonly Subject _activated = new Subject(); @@ -79,12 +82,6 @@ namespace ReactiveUI.AndroidSupport remove => PropertyChangingEventManager.RemoveHandler(this, value); } - /// - void IReactiveObject.RaisePropertyChanging(PropertyChangingEventArgs args) - { - PropertyChangingEventManager.DeliverEvent(this, args); - } - /// public event PropertyChangedEventHandler PropertyChanged { @@ -92,21 +89,10 @@ namespace ReactiveUI.AndroidSupport remove => PropertyChangedEventManager.RemoveHandler(this, value); } - /// - void IReactiveObject.RaisePropertyChanged(PropertyChangedEventArgs args) - { - PropertyChangedEventManager.DeliverEvent(this, args); - } - - /// - /// Represents an Observable that fires *before* a property is about to - /// be changed. - /// + /// public IObservable> Changing => this.GetChangingObservable(); - /// - /// Represents an Observable that fires *after* a property has changed. - /// + /// public IObservable> Changed => this.GetChangedObservable(); /// @@ -127,13 +113,19 @@ namespace ReactiveUI.AndroidSupport /// public IObservable> ActivityResult => _activityResult.AsObservable(); - /// - /// When this method is called, an object will not fire change - /// notifications (neither traditional nor Observable notifications) - /// until the return value is disposed. - /// - /// An object that, when disposed, re-enables change - /// notifications. + /// + void IReactiveObject.RaisePropertyChanging(PropertyChangingEventArgs args) + { + PropertyChangingEventManager.DeliverEvent(this, args); + } + + /// + void IReactiveObject.RaisePropertyChanged(PropertyChangedEventArgs args) + { + PropertyChangedEventManager.DeliverEvent(this, args); + } + + /// public IDisposable SuppressChangeNotifications() => IReactiveObjectExtensions.SuppressChangeNotifications(this); /// diff --git a/src/ReactiveUI.AndroidSupport/ReactivePagerAdapter.cs b/src/ReactiveUI.AndroidSupport/ReactivePagerAdapter.cs index 6606187d..637b098a 100644 --- a/src/ReactiveUI.AndroidSupport/ReactivePagerAdapter.cs +++ b/src/ReactiveUI.AndroidSupport/ReactivePagerAdapter.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using System.Collections.Specialized; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Reactive.Disposables; using System.Threading; @@ -17,13 +18,12 @@ using Object = Java.Lang.Object; namespace ReactiveUI.AndroidSupport { -#pragma warning disable SA1600 // Elements should be documented /// /// ReactivePagerAdapter is a PagerAdapter that will interface with a /// Observable change set, in a similar fashion to ReactiveTableViewSource. /// /// The view model type. - [Obsolete("ReactiveList is no longer supported. We suggest replacing it with DynamicData https://github.com/rolandpheasant/dynamicdata")] + [SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:FileMayOnlyContainASingleType", Justification = "Classes with the same class names within.")] public class ReactivePagerAdapter : PagerAdapter, IEnableLogger where TViewModel : class { @@ -32,6 +32,12 @@ namespace ReactiveUI.AndroidSupport private readonly Action _viewInitializer; private IDisposable _inner; + /// + /// Initializes a new instance of the class. + /// + /// The change set to page. + /// A function which will create the view. + /// A action which will initialize a view. public ReactivePagerAdapter( IObservable> changeSet, Func viewCreator, @@ -44,6 +50,9 @@ namespace ReactiveUI.AndroidSupport _inner = _list.Connect().Subscribe(_ => NotifyDataSetChanged()); } + /// + public override int Count => _list.Count; + /// public override bool IsViewFromObject(View view, Object @object) { @@ -64,10 +73,7 @@ namespace ReactiveUI.AndroidSupport ivf.ViewModel = data; } - if (_viewInitializer != null) - { - _viewInitializer(data, theView); - } + _viewInitializer?.Invoke(data, theView); container.AddView(theView, 0); return theView; @@ -80,9 +86,6 @@ namespace ReactiveUI.AndroidSupport container.RemoveView(view); } - /// - public override int Count => _list.Count; - /// protected override void Dispose(bool disposing) { @@ -91,10 +94,23 @@ namespace ReactiveUI.AndroidSupport } } + /// + /// ReactivePagerAdapter is a PagerAdapter that will interface with a + /// Observable change set, in a similar fashion to ReactiveTableViewSource. + /// + /// The view model type. + /// The type of collection. + [SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:FileMayOnlyContainASingleType", Justification = "Classes with the same class names within.")] public class ReactivePagerAdapter : ReactivePagerAdapter where TViewModel : class where TCollection : INotifyCollectionChanged, IEnumerable { + /// + /// Initializes a new instance of the class. + /// + /// The collection to page. + /// The function which will create the view. + /// A action which will initialize the view. public ReactivePagerAdapter( TCollection collection, Func viewCreator, diff --git a/src/ReactiveUI.AndroidSupport/ReactiveRecyclerViewAdapter.cs b/src/ReactiveUI.AndroidSupport/ReactiveRecyclerViewAdapter.cs index 8e6618aa..23c7668b 100644 --- a/src/ReactiveUI.AndroidSupport/ReactiveRecyclerViewAdapter.cs +++ b/src/ReactiveUI.AndroidSupport/ReactiveRecyclerViewAdapter.cs @@ -6,6 +6,7 @@ using System; using System.Collections.Generic; using System.Collections.Specialized; using System.ComponentModel; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Reactive.Disposables; using System.Reactive.Linq; @@ -25,6 +26,7 @@ namespace ReactiveUI.AndroidSupport /// to create the your based ViewHolder. /// /// The type of ViewModel that this adapter holds. + [SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:FileMayOnlyContainASingleType", Justification = "Classes with the same class names within.")] public abstract class ReactiveRecyclerViewAdapter : RecyclerView.Adapter where TViewModel : class, IReactiveObject { @@ -46,15 +48,15 @@ namespace ReactiveUI.AndroidSupport .Subscribe(); } + /// + public override int ItemCount => _list.Count; + /// public override void OnBindViewHolder(RecyclerView.ViewHolder holder, int position) { ((IViewFor)holder).ViewModel = _list.Items.ElementAt(position); } - /// - public override int ItemCount => _list.Count; - /// protected override void Dispose(bool disposing) { @@ -97,6 +99,7 @@ namespace ReactiveUI.AndroidSupport /// /// The type of ViewModel that this adapter holds. /// The type of collection. + [SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:FileMayOnlyContainASingleType", Justification = "Classes with the same class names within.")] public abstract class ReactiveRecyclerViewAdapter : ReactiveRecyclerViewAdapter where TViewModel : class, IReactiveObject where TCollection : ICollection, INotifyCollectionChanged @@ -110,151 +113,4 @@ namespace ReactiveUI.AndroidSupport { } } - - /// - /// A implementation that binds to a reactive view model. - /// - /// The type of the view model. - public class ReactiveRecyclerViewViewHolder : RecyclerView.ViewHolder, ILayoutViewHost, IViewFor, IReactiveNotifyPropertyChanged>, IReactiveObject - where TViewModel : class, IReactiveObject - { - private TViewModel _viewModel; - - /// - /// Initializes a new instance of the class. - /// - /// The view. - protected ReactiveRecyclerViewViewHolder(View view) - : base(view) - { - SetupRxObj(); - - Selected = Observable.FromEventPattern( - h => view.Click += h, - h => view.Click -= h) - .Select(_ => AdapterPosition); - - LongClicked = Observable.FromEventPattern( - h => view.LongClick += h, - h => view.LongClick -= h) - .Select(_ => AdapterPosition); - } - - /// - public event PropertyChangingEventHandler PropertyChanging - { - add => PropertyChangingEventManager.AddHandler(this, value); - remove => PropertyChangingEventManager.RemoveHandler(this, value); - } - - /// - public event PropertyChangedEventHandler PropertyChanged - { - add => PropertyChangedEventManager.AddHandler(this, value); - remove => PropertyChangedEventManager.RemoveHandler(this, value); - } - - /// - /// Signals that this ViewHolder has been selected. - /// - /// The is the position of this ViewHolder in the - /// and corresponds to the property. - /// - public IObservable Selected { get; } - - /// - /// Signals that this ViewHolder has been long-clicked. - /// - /// The is the position of this ViewHolder in the - /// and corresponds to the property. - /// - public IObservable LongClicked { get; } - - /// - public View View => ItemView; - - /// - public TViewModel ViewModel - { - get => _viewModel; - set => this.RaiseAndSetIfChanged(ref _viewModel, value); - } - - /// - object IViewFor.ViewModel - { - get => ViewModel; - set => ViewModel = (TViewModel)value; - } - - /// - /// Represents an Observable that fires *before* a property is about to - /// be changed. - /// - [IgnoreDataMember] - public IObservable>> Changing => this.GetChangingObservable(); - - /// - /// Represents an Observable that fires *after* a property has changed. - /// - [IgnoreDataMember] - public IObservable>> Changed => this.GetChangedObservable(); - - /// - /// Gets all public accessible properties. - /// - [IgnoreDataMember] - protected Lazy AllPublicProperties; - - /// - /// An observable sequence of thrown exceptions. - /// - [IgnoreDataMember] - public IObservable ThrownExceptions => this.GetThrownExceptionsObservable(); - - /// - /// When this method is called, an object will not fire change - /// notifications (neither traditional nor Observable notifications) - /// until the return value is disposed. - /// - /// An object that, when disposed, re-enables change - /// notifications. - public IDisposable SuppressChangeNotifications() - { - return IReactiveObjectExtensions.SuppressChangeNotifications(this); - } - - /// - /// Gets a value indicating if the change notifications are enabled. - /// - /// A value indicating whether the change notifications are enabled. - public bool AreChangeNotificationsEnabled() - { - return IReactiveObjectExtensions.AreChangeNotificationsEnabled(this); - } - - /// - void IReactiveObject.RaisePropertyChanging(PropertyChangingEventArgs args) - { - PropertyChangingEventManager.DeliverEvent(this, args); - } - - /// - void IReactiveObject.RaisePropertyChanged(PropertyChangedEventArgs args) - { - PropertyChangedEventManager.DeliverEvent(this, args); - } - - [OnDeserialized] - private void SetupRxObj(StreamingContext sc) - { - SetupRxObj(); - } - - private void SetupRxObj() - { - AllPublicProperties = new Lazy(() => - GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance).ToArray()); - } - } } diff --git a/src/ReactiveUI.AndroidSupport/ReactiveRecyclerViewViewHolder.cs b/src/ReactiveUI.AndroidSupport/ReactiveRecyclerViewViewHolder.cs new file mode 100644 index 00000000..0ec77080 --- /dev/null +++ b/src/ReactiveUI.AndroidSupport/ReactiveRecyclerViewViewHolder.cs @@ -0,0 +1,157 @@ +// 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; +using System.ComponentModel; +using System.Diagnostics.CodeAnalysis; +using System.Linq; +using System.Reactive.Linq; +using System.Reflection; +using System.Runtime.Serialization; +using Android.Support.V7.Widget; +using Android.Views; + +namespace ReactiveUI.AndroidSupport +{ + /// + /// A implementation that binds to a reactive view model. + /// + /// The type of the view model. + public class ReactiveRecyclerViewViewHolder : RecyclerView.ViewHolder, ILayoutViewHost, IViewFor, IReactiveNotifyPropertyChanged>, IReactiveObject + where TViewModel : class, IReactiveObject + { + /// + /// Gets all public accessible properties. + /// + [SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1401: Field should be private", Justification = "Legacy reasons")] + [SuppressMessage("Design", "CA1051: Do not declare visible instance fields", Justification = "Legacy reasons")] + [SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1306: Field should start with a lower case letter", Justification = "Legacy reasons")] + [IgnoreDataMember] + protected Lazy AllPublicProperties; + + private TViewModel _viewModel; + + /// + /// Initializes a new instance of the class. + /// + /// The view. + protected ReactiveRecyclerViewViewHolder(View view) + : base(view) + { + SetupRxObj(); + + Selected = Observable.FromEventPattern( + h => view.Click += h, + h => view.Click -= h) + .Select(_ => AdapterPosition); + + LongClicked = Observable.FromEventPattern( + h => view.LongClick += h, + h => view.LongClick -= h) + .Select(_ => AdapterPosition); + } + + /// + public event PropertyChangingEventHandler PropertyChanging + { + add => PropertyChangingEventManager.AddHandler(this, value); + remove => PropertyChangingEventManager.RemoveHandler(this, value); + } + + /// + public event PropertyChangedEventHandler PropertyChanged + { + add => PropertyChangedEventManager.AddHandler(this, value); + remove => PropertyChangedEventManager.RemoveHandler(this, value); + } + + /// + /// Gets an observable that signals that this ViewHolder has been selected. + /// + /// The is the position of this ViewHolder in the + /// and corresponds to the property. + /// + public IObservable Selected { get; } + + /// + /// Gets an observable that signals that this ViewHolder has been long-clicked. + /// + /// The is the position of this ViewHolder in the + /// and corresponds to the property. + /// + public IObservable LongClicked { get; } + + /// + /// Gets the current view being shown. + /// + public View View => ItemView; + + /// + public TViewModel ViewModel + { + get => _viewModel; + set => this.RaiseAndSetIfChanged(ref _viewModel, value); + } + + /// + /// Gets an observable which signals when exceptions are thrown. + /// + [IgnoreDataMember] + public IObservable ThrownExceptions => this.GetThrownExceptionsObservable(); + + /// + object IViewFor.ViewModel + { + get => ViewModel; + set => ViewModel = (TViewModel)value; + } + + /// + [IgnoreDataMember] + public IObservable>> Changing => this.GetChangingObservable(); + + /// + [IgnoreDataMember] + public IObservable>> Changed => this.GetChangedObservable(); + + /// + public IDisposable SuppressChangeNotifications() + { + return IReactiveObjectExtensions.SuppressChangeNotifications(this); + } + + /// + /// Gets if change notifications via the INotifyPropertyChanged interface are being sent. + /// + /// A value indicating whether change notifications are enabled or not. + public bool AreChangeNotificationsEnabled() + { + return IReactiveObjectExtensions.AreChangeNotificationsEnabled(this); + } + + /// + void IReactiveObject.RaisePropertyChanging(PropertyChangingEventArgs args) + { + PropertyChangingEventManager.DeliverEvent(this, args); + } + + /// + void IReactiveObject.RaisePropertyChanged(PropertyChangedEventArgs args) + { + PropertyChangedEventManager.DeliverEvent(this, args); + } + + [OnDeserialized] + private void SetupRxObj(StreamingContext sc) + { + SetupRxObj(); + } + + private void SetupRxObj() + { + AllPublicProperties = new Lazy(() => + GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance).ToArray()); + } + } +} diff --git a/src/ReactiveUI.AndroidSupport/ReactiveUI.AndroidSupport.csproj b/src/ReactiveUI.AndroidSupport/ReactiveUI.AndroidSupport.csproj index 99ef5baa..170652a6 100644 --- a/src/ReactiveUI.AndroidSupport/ReactiveUI.AndroidSupport.csproj +++ b/src/ReactiveUI.AndroidSupport/ReactiveUI.AndroidSupport.csproj @@ -2,8 +2,6 @@ MonoAndroid81 - ReactiveUI.AndroidSupport - ReactiveUI.AndroidSupport ReactiveUI extensions for the Android Support Library ReactiveUI.AndroidSupport diff --git a/src/ReactiveUI.Blend/FollowObservableStateBehavior.cs b/src/ReactiveUI.Blend/FollowObservableStateBehavior.cs index d2c050db..657e9c77 100644 --- a/src/ReactiveUI.Blend/FollowObservableStateBehavior.cs +++ b/src/ReactiveUI.Blend/FollowObservableStateBehavior.cs @@ -14,6 +14,8 @@ using System.Windows.Controls; using System.Windows.Interactivity; #endif +#pragma warning disable SA1201 // A field should not follow a property - macro if statements make this hard + namespace ReactiveUI.Blend { /// @@ -79,18 +81,6 @@ namespace ReactiveUI.Blend /// public bool AutoResubscribeOnError { get; set; } - /// - protected override void OnDetaching() - { - if (_watcher != null) - { - _watcher.Dispose(); - _watcher = null; - } - - base.OnDetaching(); - } - /// /// Called when [state observable changed]. /// @@ -132,5 +122,17 @@ namespace ReactiveUI.Blend OnStateObservableChanged(@this, e); }); } + + /// + protected override void OnDetaching() + { + if (_watcher != null) + { + _watcher.Dispose(); + _watcher = null; + } + + base.OnDetaching(); + } } } diff --git a/src/ReactiveUI.Blend/Platforms/net461/ObservableTrigger.cs b/src/ReactiveUI.Blend/Platforms/net461/ObservableTrigger.cs index 7bcee486..d6dc6025 100644 --- a/src/ReactiveUI.Blend/Platforms/net461/ObservableTrigger.cs +++ b/src/ReactiveUI.Blend/Platforms/net461/ObservableTrigger.cs @@ -17,6 +17,14 @@ namespace ReactiveUI.Blend /// public class ObservableTrigger : TriggerBase { + /// + /// The dependency property registration for the Observable property. + /// + public static readonly DependencyProperty ObservableProperty = + DependencyProperty.Register("Observable", typeof(IObservable), typeof(ObservableTrigger), new PropertyMetadata(OnObservableChanged)); + + private IDisposable _watcher; + /// /// Gets or sets the observable which will activate the trigger. /// @@ -27,18 +35,10 @@ namespace ReactiveUI.Blend } /// - /// The dependency property registration for the Observable property. - /// - public static readonly DependencyProperty ObservableProperty = - DependencyProperty.Register("Observable", typeof(IObservable), typeof(ObservableTrigger), new PropertyMetadata(OnObservableChanged)); - - /// - /// Gets or set if we should resubscribe the trigger if there is a error when running the IObservable. + /// Gets or sets a value indicating whether to resubscribe the trigger if there is a error when running the IObservable. /// public bool AutoResubscribeOnError { get; set; } - private IDisposable _watcher; - /// /// Called when [observable changed]. /// @@ -46,23 +46,23 @@ namespace ReactiveUI.Blend /// The instance containing the event data. protected static void OnObservableChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) { - ObservableTrigger This = (ObservableTrigger)sender; - if (This._watcher != null) + ObservableTrigger triggerItem = (ObservableTrigger)sender; + if (triggerItem._watcher != null) { - This._watcher.Dispose(); - This._watcher = null; + triggerItem._watcher.Dispose(); + triggerItem._watcher = null; } - This._watcher = ((IObservable)e.NewValue).ObserveOn(RxApp.MainThreadScheduler).Subscribe( - x => This.InvokeActions(x), + triggerItem._watcher = ((IObservable)e.NewValue).ObserveOn(RxApp.MainThreadScheduler).Subscribe( + x => triggerItem.InvokeActions(x), ex => { - if (!This.AutoResubscribeOnError) + if (!triggerItem.AutoResubscribeOnError) { return; } - OnObservableChanged(This, e); + OnObservableChanged(triggerItem, e); }); } } diff --git a/src/ReactiveUI.Blend/Platforms/uap10.0.16299/Behavior.cs b/src/ReactiveUI.Blend/Platforms/uap10.0.16299/Behavior.cs index adef91c1..7659139a 100644 --- a/src/ReactiveUI.Blend/Platforms/uap10.0.16299/Behavior.cs +++ b/src/ReactiveUI.Blend/Platforms/uap10.0.16299/Behavior.cs @@ -17,6 +17,14 @@ namespace ReactiveUI.Blend public class Behavior : DependencyObject, IBehavior where T : DependencyObject { + /// + /// Gets the associated object. + /// + public T AssociatedObject { get; private set; } + + /// + DependencyObject IBehavior.AssociatedObject => AssociatedObject; + /// public virtual void Attach(DependencyObject associatedObject) { @@ -53,16 +61,5 @@ namespace ReactiveUI.Blend protected virtual void OnDetaching() { } - - /// - /// Gets the associated object. - /// - public T AssociatedObject { get; private set; } - - /// - DependencyObject IBehavior.AssociatedObject - { - get { return AssociatedObject; } - } } } diff --git a/src/ReactiveUI.Blend/Platforms/uap10.0.16299/ObservableTriggerBehavior.cs b/src/ReactiveUI.Blend/Platforms/uap10.0.16299/ObservableTriggerBehavior.cs index 64a4c794..0bac9066 100644 --- a/src/ReactiveUI.Blend/Platforms/uap10.0.16299/ObservableTriggerBehavior.cs +++ b/src/ReactiveUI.Blend/Platforms/uap10.0.16299/ObservableTriggerBehavior.cs @@ -19,8 +19,26 @@ namespace ReactiveUI.Blend /// Behavior that response to triggered observables. /// [ContentProperty(Name = "Actions")] - public sealed class ObservableTriggerBehavior : Behavior + public sealed class ObservableTriggerBehavior : Behavior, IDisposable { + /// + /// The observable dependency property. + /// + public static readonly DependencyProperty ObservableProperty = + DependencyProperty.Register("Observable", typeof(IObservable), typeof(ObservableTriggerBehavior), new PropertyMetadata(null, OnObservableChanged)); + + /// + /// The actions dependency property. + /// + public static readonly DependencyProperty ActionsProperty = + DependencyProperty.Register("Actions", typeof(ActionCollection), typeof(ObservableTriggerBehavior), new PropertyMetadata(null)); + + /// + /// The source object dependency property. + /// + public static readonly DependencyProperty SourceObjectProperty = + DependencyProperty.Register("SourceObject", typeof(object), typeof(ObservableTriggerBehavior), new PropertyMetadata(null, OnSourceObjectChanged)); + private object _resolvedSource; private SerialDisposable _watcher; @@ -52,12 +70,6 @@ namespace ReactiveUI.Blend } } - /// - /// The actions dependency property. - /// - public static readonly DependencyProperty ActionsProperty = - DependencyProperty.Register("Actions", typeof(ActionCollection), typeof(ObservableTriggerBehavior), new PropertyMetadata(null)); - /// /// Gets or sets the source object. /// @@ -67,12 +79,6 @@ namespace ReactiveUI.Blend set => SetValue(ObservableTriggerBehavior.SourceObjectProperty, value); } - /// - /// The source object dependency property. - /// - public static readonly DependencyProperty SourceObjectProperty = - DependencyProperty.Register("SourceObject", typeof(object), typeof(ObservableTriggerBehavior), new PropertyMetadata(null, OnSourceObjectChanged)); - /// /// Gets or sets a value indicating whether [automatic resubscribe on error]. /// @@ -87,11 +93,44 @@ namespace ReactiveUI.Blend set => SetValue(ObservableProperty, value); } - /// - /// The observable dependency property. - /// - public static readonly DependencyProperty ObservableProperty = - DependencyProperty.Register("Observable", typeof(IObservable), typeof(ObservableTriggerBehavior), new PropertyMetadata(null, OnObservableChanged)); + /// + public void Dispose() + { + _watcher?.Dispose(); + } + + /// + protected override void OnAttached() + { + base.OnAttached(); + SetResolvedSource(ComputeResolvedSource()); + } + + /// + protected override void OnDetaching() + { + SetResolvedSource(null); + base.OnDetaching(); + + _watcher.Dispose(); + } + + private static void OnObservableChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) + { + ObservableTriggerBehavior @this = (ObservableTriggerBehavior)sender; + + @this._watcher.Disposable = ((IObservable)e.NewValue).ObserveOn(RxApp.MainThreadScheduler).Subscribe( + x => Interaction.ExecuteActions(@this._resolvedSource, @this.Actions, x), + ex => + { + if (!@this.AutoResubscribeOnError) + { + return; + } + + OnObservableChanged(@this, e); + }); + } private static void OnSourceObjectChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs args) { @@ -119,38 +158,5 @@ namespace ReactiveUI.Blend return AssociatedObject; } - - private static void OnObservableChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) - { - ObservableTriggerBehavior @this = (ObservableTriggerBehavior)sender; - - @this._watcher.Disposable = ((IObservable)e.NewValue).ObserveOn(RxApp.MainThreadScheduler).Subscribe( - x => Interaction.ExecuteActions(@this._resolvedSource, @this.Actions, x), - ex => - { - if (!@this.AutoResubscribeOnError) - { - return; - } - - OnObservableChanged(@this, e); - }); - } - - /// - protected override void OnAttached() - { - base.OnAttached(); - SetResolvedSource(ComputeResolvedSource()); - } - - /// - protected override void OnDetaching() - { - SetResolvedSource(null); - base.OnDetaching(); - - _watcher.Dispose(); - } } } diff --git a/src/ReactiveUI.Events.WPF/ReactiveUI.Events.WPF.csproj b/src/ReactiveUI.Events.WPF/ReactiveUI.Events.WPF.csproj index be556e81..d9fe1ed1 100644 --- a/src/ReactiveUI.Events.WPF/ReactiveUI.Events.WPF.csproj +++ b/src/ReactiveUI.Events.WPF/ReactiveUI.Events.WPF.csproj @@ -6,6 +6,7 @@ Provides Observable-based events API for WPF UI controls/eventhandlers. The contents of this package is automatically generated, please target pull-requests to the code generator. ReactiveUI.Events.WPF true + $(NoWarn);CS1570;CA1812 diff --git a/src/ReactiveUI.Events.Winforms/ReactiveUI.Events.Winforms.csproj b/src/ReactiveUI.Events.Winforms/ReactiveUI.Events.Winforms.csproj index 60675043..181920cb 100644 --- a/src/ReactiveUI.Events.Winforms/ReactiveUI.Events.Winforms.csproj +++ b/src/ReactiveUI.Events.Winforms/ReactiveUI.Events.Winforms.csproj @@ -6,6 +6,7 @@ Provides Observable-based events API for Winforms UI controls/eventhandlers. The contents of this package is automatically generated, please target pull-requests to the code generator. ReactiveUI.Events.Winforms true + $(NoWarn);CS1570;CA1812 diff --git a/src/ReactiveUI.Events.XamForms/ReactiveUI.Events.XamForms.csproj b/src/ReactiveUI.Events.XamForms/ReactiveUI.Events.XamForms.csproj index d1d2dc8b..8128cfe1 100644 --- a/src/ReactiveUI.Events.XamForms/ReactiveUI.Events.XamForms.csproj +++ b/src/ReactiveUI.Events.XamForms/ReactiveUI.Events.XamForms.csproj @@ -5,6 +5,7 @@ ReactiveUI.Events Provides Observable-based events API for Xamarin Forms UI controls/eventhandlers. The contents of this package is automatically generated, please target pull-requests to the code generator. ReactiveUI.Events.XamForms + $(NoWarn);CS1570;CA1812 diff --git a/src/ReactiveUI.Events/ReactiveUI.Events.csproj b/src/ReactiveUI.Events/ReactiveUI.Events.csproj index 111c103f..5eca28ca 100644 --- a/src/ReactiveUI.Events/ReactiveUI.Events.csproj +++ b/src/ReactiveUI.Events/ReactiveUI.Events.csproj @@ -5,6 +5,7 @@ ReactiveUI.Events Provides Observable-based events API for common UI controls/eventhandlers. The contents of this package is automatically generated, please target pull-requests to the code generator. ReactiveUI.Events + $(NoWarn);CS1570;CA1812 diff --git a/src/ReactiveUI.Events/SingleAwaitSubject.cs b/src/ReactiveUI.Events/SingleAwaitSubject.cs index e998ffec..f30ca07d 100644 --- a/src/ReactiveUI.Events/SingleAwaitSubject.cs +++ b/src/ReactiveUI.Events/SingleAwaitSubject.cs @@ -8,7 +8,7 @@ using System.Reactive.Subjects; namespace ReactiveUI.Events { - internal class SingleAwaitSubject : ISubject + internal sealed class SingleAwaitSubject : ISubject, IDisposable { private readonly Subject _inner = new Subject(); @@ -36,5 +36,11 @@ namespace ReactiveUI.Events { return _inner.Subscribe(observer); } + + /// + public void Dispose() + { + _inner?.Dispose(); + } } } diff --git a/src/ReactiveUI.Fody.Helpers/ReactiveDependencyAttribute.cs b/src/ReactiveUI.Fody.Helpers/ReactiveDependencyAttribute.cs index c01e7aa6..803530a3 100644 --- a/src/ReactiveUI.Fody.Helpers/ReactiveDependencyAttribute.cs +++ b/src/ReactiveUI.Fody.Helpers/ReactiveDependencyAttribute.cs @@ -27,12 +27,12 @@ namespace ReactiveUI.Fody.Helpers } /// - /// The name of the backing property. + /// Gets the name of the backing property. /// public string Target => _targetName; /// - /// Target property on the backing property. + /// Gets or sets the target property on the backing property. /// public string TargetProperty { get; set; } } diff --git a/src/ReactiveUI.Fody.Helpers/ReactiveUI.Fody.Helpers.csproj b/src/ReactiveUI.Fody.Helpers/ReactiveUI.Fody.Helpers.csproj index a7aba4fa..29ad337e 100644 --- a/src/ReactiveUI.Fody.Helpers/ReactiveUI.Fody.Helpers.csproj +++ b/src/ReactiveUI.Fody.Helpers/ReactiveUI.Fody.Helpers.csproj @@ -12,8 +12,8 @@ - - + + diff --git a/src/ReactiveUI.Fody.Tests/API/ApiApprovalTests.ReactiveUI_Fody.approved.txt b/src/ReactiveUI.Fody.Tests/API/ApiApprovalTests.ReactiveUIFody.approved.txt similarity index 94% rename from src/ReactiveUI.Fody.Tests/API/ApiApprovalTests.ReactiveUI_Fody.approved.txt rename to src/ReactiveUI.Fody.Tests/API/ApiApprovalTests.ReactiveUIFody.approved.txt index 8e2b29a8..4f772e7c 100644 --- a/src/ReactiveUI.Fody.Tests/API/ApiApprovalTests.ReactiveUI_Fody.approved.txt +++ b/src/ReactiveUI.Fody.Tests/API/ApiApprovalTests.ReactiveUIFody.approved.txt @@ -1,4 +1,4 @@ -[assembly: System.Runtime.CompilerServices.InternalsVisibleToAttribute("ReactiveUI.AndroidSupport")] +[assembly: System.Runtime.CompilerServices.InternalsVisibleToAttribute("ReactiveUI.AndroidSupport")] [assembly: System.Runtime.CompilerServices.InternalsVisibleToAttribute("ReactiveUI.Tests")] [assembly: System.Runtime.CompilerServices.InternalsVisibleToAttribute("ReactiveUI.Winforms")] [assembly: System.Runtime.CompilerServices.InternalsVisibleToAttribute("ReactiveUI.Wpf")] diff --git a/src/ReactiveUI.Fody.Tests/API/ApiApprovalTests.cs b/src/ReactiveUI.Fody.Tests/API/ApiApprovalTests.cs index e6d3e12b..bd43f57d 100644 --- a/src/ReactiveUI.Fody.Tests/API/ApiApprovalTests.cs +++ b/src/ReactiveUI.Fody.Tests/API/ApiApprovalTests.cs @@ -16,7 +16,7 @@ namespace ReactiveUI.Fody.Tests.API public class ApiApprovalTests { [Fact] - public void ReactiveUI_Fody() + public void ReactiveUIFody() { var publicApi = Filter(ApiGenerator.GeneratePublicApi(typeof(ReactiveAttribute).Assembly)); publicApi.ShouldMatchApproved(); @@ -24,14 +24,15 @@ namespace ReactiveUI.Fody.Tests.API private static string Filter(string text) { - return string.Join(Environment.NewLine, text.Split(new[] - { - Environment.NewLine - }, StringSplitOptions.RemoveEmptyEntries) - .Where(l => !l.StartsWith("[assembly: AssemblyVersion(")) - .Where(l => !l.StartsWith("[assembly: AssemblyFileVersion(")) - .Where(l => !l.StartsWith("[assembly: AssemblyInformationalVersion(")) - .Where(l => !string.IsNullOrWhiteSpace(l))); + return string.Join(Environment.NewLine, text.Split( + new[] + { + Environment.NewLine + }, StringSplitOptions.RemoveEmptyEntries) + .Where(l => !l.StartsWith("[assembly: AssemblyVersion(")) + .Where(l => !l.StartsWith("[assembly: AssemblyFileVersion(")) + .Where(l => !l.StartsWith("[assembly: AssemblyInformationalVersion(")) + .Where(l => !string.IsNullOrWhiteSpace(l))); } } } diff --git a/src/ReactiveUI.Fody.Tests/FodyWeavers.xml b/src/ReactiveUI.Fody.Tests/FodyWeavers.xml index 394cd180..777f1e06 100644 --- a/src/ReactiveUI.Fody.Tests/FodyWeavers.xml +++ b/src/ReactiveUI.Fody.Tests/FodyWeavers.xml @@ -1,10 +1,9 @@ - + - - - + + \ No newline at end of file diff --git a/src/ReactiveUI.Fody.Tests/FodyWeavers.xsd b/src/ReactiveUI.Fody.Tests/FodyWeavers.xsd new file mode 100644 index 00000000..f3ac4762 --- /dev/null +++ b/src/ReactiveUI.Fody.Tests/FodyWeavers.xsd @@ -0,0 +1,26 @@ + + + + + + + + + + + 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed. + + + + + A comma-separated list of error codes that can be safely ignored in assembly verification. + + + + + 'false' to turn off automatic generation of the XML Schema file. + + + + + \ No newline at end of file diff --git a/src/ReactiveUI.Fody.Tests/Issues/Issue10Tests.cs b/src/ReactiveUI.Fody.Tests/Issues/Issue10Tests.cs index 47e2e686..0e699a03 100644 --- a/src/ReactiveUI.Fody.Tests/Issues/Issue10Tests.cs +++ b/src/ReactiveUI.Fody.Tests/Issues/Issue10Tests.cs @@ -21,6 +21,11 @@ namespace ReactiveUI.Fody.Tests.Issues private class TestModel : ReactiveObject { + public TestModel() + { + OtherProperty = MyProperty; + } + [ObservableAsProperty] public string MyProperty { get; private set; } @@ -31,11 +36,6 @@ namespace ReactiveUI.Fody.Tests.Issues public DateTime MyDateTimeProperty { get; private set; } public string OtherProperty { get; private set; } - - public TestModel() - { - OtherProperty = MyProperty; - } } } } diff --git a/src/ReactiveUI.Fody.Tests/Issues/Issue11Tests.cs b/src/ReactiveUI.Fody.Tests/Issues/Issue11Tests.cs index 8cf9d59e..0111faf7 100644 --- a/src/ReactiveUI.Fody.Tests/Issues/Issue11Tests.cs +++ b/src/ReactiveUI.Fody.Tests/Issues/Issue11Tests.cs @@ -19,12 +19,16 @@ namespace ReactiveUI.Fody.Tests.Issues public class TestModel : ReactiveObject { - public extern string MyProperty { [ObservableAsProperty]get; } - public TestModel(string myProperty) { Observable.Return(myProperty).ToPropertyEx(this, x => x.MyProperty); } + + public extern string MyProperty + { + [ObservableAsProperty] + get; + } } } } diff --git a/src/ReactiveUI.Fody.Tests/Issues/Issue13Tests.cs b/src/ReactiveUI.Fody.Tests/Issues/Issue13Tests.cs index 2210e5d7..cab98ec1 100644 --- a/src/ReactiveUI.Fody.Tests/Issues/Issue13Tests.cs +++ b/src/ReactiveUI.Fody.Tests/Issues/Issue13Tests.cs @@ -24,15 +24,17 @@ namespace ReactiveUI.Fody.Tests.Issues private class VM : ReactiveObject { - [ObservableAsProperty] public double P1 { get; } - - [ObservableAsProperty] public double P2 { get; } - public VM() { Observable.Return(0.0).ToPropertyEx(this, vm => vm.P1); this.WhenAnyValue(vm => vm.P1).ToPropertyEx(this, vm => vm.P2); } + + [ObservableAsProperty] + public double P1 { get; } + + [ObservableAsProperty] + public double P2 { get; } } } } diff --git a/src/ReactiveUI.Fody.Tests/ObservableAsPropertyTests.cs b/src/ReactiveUI.Fody.Tests/ObservableAsPropertyTests.cs index f16ead90..7addca6f 100644 --- a/src/ReactiveUI.Fody.Tests/ObservableAsPropertyTests.cs +++ b/src/ReactiveUI.Fody.Tests/ObservableAsPropertyTests.cs @@ -19,13 +19,13 @@ namespace ReactiveUI.Fody.Tests public class TestModel : ReactiveObject { - [ObservableAsProperty] - public string TestProperty { get; private set; } - public TestModel() { Observable.Return("foo").ToPropertyEx(this, x => x.TestProperty); } + + [ObservableAsProperty] + public string TestProperty { get; private set; } } } } diff --git a/src/ReactiveUI.Fody.Tests/ReactiveUI.Fody.Tests.csproj b/src/ReactiveUI.Fody.Tests/ReactiveUI.Fody.Tests.csproj index 15a9d45f..29b0812e 100644 --- a/src/ReactiveUI.Fody.Tests/ReactiveUI.Fody.Tests.csproj +++ b/src/ReactiveUI.Fody.Tests/ReactiveUI.Fody.Tests.csproj @@ -33,6 +33,6 @@ - + diff --git a/src/ReactiveUI.Fody/ObservableAsPropertyWeaver.cs b/src/ReactiveUI.Fody/ObservableAsPropertyWeaver.cs index 06ceaa2f..0fc89488 100644 --- a/src/ReactiveUI.Fody/ObservableAsPropertyWeaver.cs +++ b/src/ReactiveUI.Fody/ObservableAsPropertyWeaver.cs @@ -24,7 +24,7 @@ namespace ReactiveUI.Fody public ModuleDefinition ModuleDefinition { get; set; } /// - /// Will log an MessageImportance.High message to MSBuild. OPTIONAL. + /// Gets or sets a action that will log an MessageImportance.High message to MSBuild. OPTIONAL. /// /// /// The log information. @@ -32,7 +32,7 @@ namespace ReactiveUI.Fody public Action LogInfo { get; set; } /// - /// Locates a type from referenced assemblies by name. + /// Gets a function that will find a type from referenced assemblies by name. /// public Func FindType { get; internal set; } @@ -135,7 +135,7 @@ namespace ReactiveUI.Fody } else if (type.CompareTo(ModuleDefinition.TypeSystem.Single)) { - il.Emit(OpCodes.Ldc_R4, (float)0); + il.Emit(OpCodes.Ldc_R4, 0F); } else if (type.CompareTo(ModuleDefinition.TypeSystem.Int64)) { @@ -143,7 +143,7 @@ namespace ReactiveUI.Fody } else if (type.CompareTo(ModuleDefinition.TypeSystem.Double)) { - il.Emit(OpCodes.Ldc_R8, (double)0); + il.Emit(OpCodes.Ldc_R8, 0D); } else if (type.IsGenericParameter || type.IsValueType) { diff --git a/src/ReactiveUI.Fody/ReactiveDependencyPropertyWeaver.cs b/src/ReactiveUI.Fody/ReactiveDependencyPropertyWeaver.cs index fb07ce6b..9e350ceb 100644 --- a/src/ReactiveUI.Fody/ReactiveDependencyPropertyWeaver.cs +++ b/src/ReactiveUI.Fody/ReactiveDependencyPropertyWeaver.cs @@ -24,7 +24,7 @@ namespace ReactiveUI.Fody public ModuleDefinition ModuleDefinition { get; set; } /// - /// Will log an MessageImportance.High message to MSBuild. OPTIONAL. + /// Gets or sets a action that will log an MessageImportance.High message to MSBuild. OPTIONAL. /// /// /// The log information. @@ -32,7 +32,7 @@ namespace ReactiveUI.Fody public Action LogInfo { get; set; } /// - /// Will log an error message to MSBuild. OPTIONAL. + /// Gets or sets a action which will log an error message to MSBuild. OPTIONAL. /// /// /// The log error. diff --git a/src/ReactiveUI.Fody/ReactiveUI.Fody.csproj b/src/ReactiveUI.Fody/ReactiveUI.Fody.csproj index 4e16fba5..3e6757a2 100644 --- a/src/ReactiveUI.Fody/ReactiveUI.Fody.csproj +++ b/src/ReactiveUI.Fody/ReactiveUI.Fody.csproj @@ -8,6 +8,6 @@ - + \ No newline at end of file diff --git a/src/ReactiveUI.Fody/ReactiveUIPropertyWeaver.cs b/src/ReactiveUI.Fody/ReactiveUIPropertyWeaver.cs index 2d73b53d..0a3938fd 100644 --- a/src/ReactiveUI.Fody/ReactiveUIPropertyWeaver.cs +++ b/src/ReactiveUI.Fody/ReactiveUIPropertyWeaver.cs @@ -25,7 +25,7 @@ namespace ReactiveUI.Fody public ModuleDefinition ModuleDefinition { get; set; } /// - /// Will log an MessageImportance.High message to MSBuild. OPTIONAL. + /// Gets or sets a action that will log an MessageImportance.High message to MSBuild. OPTIONAL. /// /// /// The log information. @@ -33,7 +33,7 @@ namespace ReactiveUI.Fody public Action LogInfo { get; set; } /// - /// Will log an error message to MSBuild. OPTIONAL. + /// Gets or sets an action that will log an error message to MSBuild. OPTIONAL. /// /// /// The log error. diff --git a/src/ReactiveUI.Tests/API/ApiApprovalTests.ReactiveUI.approved.txt b/src/ReactiveUI.Tests/API/ApiApprovalTests.ReactiveUI.approved.txt index 54ae8b01..29ef2ee6 100644 --- a/src/ReactiveUI.Tests/API/ApiApprovalTests.ReactiveUI.approved.txt +++ b/src/ReactiveUI.Tests/API/ApiApprovalTests.ReactiveUI.approved.txt @@ -259,6 +259,11 @@ namespace ReactiveUI TViewModel ViewModel { get; } System.Linq.Expressions.Expression ViewModelExpression { get; } } + public interface IReactiveCommand : ReactiveUI.IHandleObservableErrors, System.IDisposable + { + System.IObservable CanExecute { get; } + System.IObservable IsExecuting { get; } + } public interface IReactiveNotifyPropertyChanged { System.IObservable> Changed { get; } @@ -486,7 +491,7 @@ namespace ReactiveUI public override System.IObservable Execute(TParam parameter = null) { } public override System.IDisposable Subscribe(System.IObserver observer) { } } - public abstract class ReactiveCommandBase : ReactiveUI.IHandleObservableErrors, System.IDisposable, System.IObservable, System.Windows.Input.ICommand + public abstract class ReactiveCommandBase : ReactiveUI.IHandleObservableErrors, ReactiveUI.IReactiveCommand, System.IDisposable, System.IObservable, System.Windows.Input.ICommand { protected ReactiveCommandBase() { } public abstract System.IObservable CanExecute { get; } diff --git a/src/ReactiveUI.Tests/API/ApiApprovalTests.Winforms.approved.txt b/src/ReactiveUI.Tests/API/ApiApprovalTests.Winforms.approved.txt index 7e120523..a7871834 100644 --- a/src/ReactiveUI.Tests/API/ApiApprovalTests.Winforms.approved.txt +++ b/src/ReactiveUI.Tests/API/ApiApprovalTests.Winforms.approved.txt @@ -14,6 +14,9 @@ namespace ReactiveUI.Winforms public System.IDisposable BindCommandToObject(System.Windows.Input.ICommand command, object target, System.IObservable commandParameter, string eventName) { } public int GetAffinityForObject(System.Type type, bool hasEventTarget) { } } + [System.ObsoleteAttribute("ReactiveList is no longer supported. We suggest replacing it with DynamicData htt" + + "ps://github.com/rolandpheasant/dynamicdata")] + public interface IReactiveDerivedBindingList : ReactiveUI.INotifyCollectionChanging, ReactiveUI.INotifyPropertyChanging, ReactiveUI.IReactiveObject, ReactiveUI.Legacy.IReactiveCollection, ReactiveUI.Legacy.IReactiveDerivedList, ReactiveUI.Legacy.IReactiveNotifyCollectionChanged, ReactiveUI.Legacy.IReactiveNotifyCollectionItemChanged, ReactiveUI.Legacy.IReadOnlyReactiveCollection, ReactiveUI.Legacy.IReadOnlyReactiveList, Splat.IEnableLogger, System.Collections.Generic.IEnumerable, System.Collections.Generic.IReadOnlyCollection, System.Collections.Generic.IReadOnlyList, System.Collections.ICollection, System.Collections.IEnumerable, System.Collections.IList, System.Collections.Specialized.INotifyCollectionChanged, System.ComponentModel.IBindingList, System.ComponentModel.INotifyPropertyChanged, System.IDisposable { } public class PlatformOperations { public PlatformOperations() { } @@ -92,21 +95,18 @@ namespace ReactiveUI.Winforms } namespace ReactiveUI.Winforms.Legacy { - [System.ObsoleteAttribute("ReactiveList is no longer supported. We suggest replacing it with DynamicData htt" + - "ps://github.com/rolandpheasant/dynamicdata")] - public interface IReactiveDerivedBindingList : ReactiveUI.INotifyCollectionChanging, ReactiveUI.INotifyPropertyChanging, ReactiveUI.IReactiveObject, ReactiveUI.Legacy.IReactiveCollection, ReactiveUI.Legacy.IReactiveDerivedList, ReactiveUI.Legacy.IReactiveNotifyCollectionChanged, ReactiveUI.Legacy.IReactiveNotifyCollectionItemChanged, ReactiveUI.Legacy.IReadOnlyReactiveCollection, ReactiveUI.Legacy.IReadOnlyReactiveList, Splat.IEnableLogger, System.Collections.Generic.IEnumerable, System.Collections.Generic.IReadOnlyCollection, System.Collections.Generic.IReadOnlyList, System.Collections.ICollection, System.Collections.IEnumerable, System.Collections.IList, System.Collections.Specialized.INotifyCollectionChanged, System.ComponentModel.IBindingList, System.ComponentModel.INotifyPropertyChanged, System.IDisposable { } [System.ObsoleteAttribute("ReactiveList is no longer supported. We suggest replacing it with DynamicData htt" + "ps://github.com/rolandpheasant/dynamicdata")] public class static ObservableCollectionMixin { - public static ReactiveUI.Winforms.Legacy.IReactiveDerivedBindingList CreateDerivedBindingList(this System.Collections.Generic.IEnumerable @this, System.Func selector, System.Action removed, System.Func filter = null, System.Func orderer = null, System.IObservable signalReset = null) { } - public static ReactiveUI.Winforms.Legacy.IReactiveDerivedBindingList CreateDerivedBindingList(this System.Collections.Generic.IEnumerable @this, System.Func selector, System.Func filter = null, System.Func orderer = null, System.IObservable signalReset = null) { } - public static ReactiveUI.Winforms.Legacy.IReactiveDerivedBindingList CreateDerivedBindingList(this System.Collections.Generic.IEnumerable @this, System.Func selector, System.Action removed, System.Func filter = null, System.Func orderer = null) { } - public static ReactiveUI.Winforms.Legacy.IReactiveDerivedBindingList CreateDerivedBindingList(this System.Collections.Generic.IEnumerable @this, System.Func selector, System.Func filter = null, System.Func orderer = null) { } + public static ReactiveUI.Winforms.IReactiveDerivedBindingList CreateDerivedBindingList(this System.Collections.Generic.IEnumerable collection, System.Func selector, System.Action removed, System.Func filter = null, System.Func orderer = null, System.IObservable signalReset = null) { } + public static ReactiveUI.Winforms.IReactiveDerivedBindingList CreateDerivedBindingList(this System.Collections.Generic.IEnumerable collection, System.Func selector, System.Func filter = null, System.Func orderer = null, System.IObservable signalReset = null) { } + public static ReactiveUI.Winforms.IReactiveDerivedBindingList CreateDerivedBindingList(this System.Collections.Generic.IEnumerable collection, System.Func selector, System.Action removed, System.Func filter = null, System.Func orderer = null) { } + public static ReactiveUI.Winforms.IReactiveDerivedBindingList CreateDerivedBindingList(this System.Collections.Generic.IEnumerable collection, System.Func selector, System.Func filter = null, System.Func orderer = null) { } } [System.ObsoleteAttribute("ReactiveList is no longer supported. We suggest replacing it with DynamicData htt" + "ps://github.com/rolandpheasant/dynamicdata")] - public class ReactiveBindingList : ReactiveUI.Legacy.ReactiveList, System.Collections.Generic.ICollection, System.Collections.Generic.IEnumerable, System.Collections.Generic.IList, System.Collections.ICollection, System.Collections.IEnumerable, System.Collections.IList, System.ComponentModel.IBindingList, System.ComponentModel.ICancelAddNew, System.ComponentModel.IRaiseItemChangedEvents + public class ReactiveBindingList : ReactiveUI.Legacy.ReactiveList, System.Collections.ICollection, System.Collections.IEnumerable, System.Collections.IList, System.ComponentModel.IBindingList, System.ComponentModel.ICancelAddNew, System.ComponentModel.IRaiseItemChangedEvents { public ReactiveBindingList() { } public ReactiveBindingList(System.Collections.Generic.IEnumerable items) { } diff --git a/src/ReactiveUI.Tests/API/ApiApprovalTests.cs b/src/ReactiveUI.Tests/API/ApiApprovalTests.cs index dce35a3f..ae2a0381 100644 --- a/src/ReactiveUI.Tests/API/ApiApprovalTests.cs +++ b/src/ReactiveUI.Tests/API/ApiApprovalTests.cs @@ -45,14 +45,16 @@ namespace ReactiveUI.Tests.API private static string Filter(string text) { - return string.Join(Environment.NewLine, text.Split(new[] - { - Environment.NewLine - }, StringSplitOptions.RemoveEmptyEntries) - .Where(l => !l.StartsWith("[assembly: AssemblyVersion(")) - .Where(l => !l.StartsWith("[assembly: AssemblyFileVersion(")) - .Where(l => !l.StartsWith("[assembly: AssemblyInformationalVersion(")) - .Where(l => !string.IsNullOrWhiteSpace(l))); + return string.Join(Environment.NewLine, text.Split( + new[] + { + Environment.NewLine + }, StringSplitOptions.RemoveEmptyEntries) + .Where(l => + !l.StartsWith("[assembly: AssemblyVersion(") && + !l.StartsWith("[assembly: AssemblyFileVersion(") && + !l.StartsWith("[assembly: AssemblyInformationalVersion(") && + !string.IsNullOrWhiteSpace(l))); } } } diff --git a/src/ReactiveUI.Tests/AutoPersistHelperTest.cs b/src/ReactiveUI.Tests/AutoPersistHelperTest.cs index d6f80e7f..9470e712 100644 --- a/src/ReactiveUI.Tests/AutoPersistHelperTest.cs +++ b/src/ReactiveUI.Tests/AutoPersistHelperTest.cs @@ -42,13 +42,14 @@ namespace ReactiveUI.Tests var manualSave = new Subject(); var timesSaved = 0; - fixture.AutoPersist(x => - { - timesSaved++; - return Observables.Unit; - }, - manualSave, - TimeSpan.FromMilliseconds(100)); + fixture.AutoPersist( + _ => + { + timesSaved++; + return Observables.Unit; + }, + manualSave, + TimeSpan.FromMilliseconds(100)); // No changes = no saving sched.AdvanceByMs(2 * 100); @@ -70,13 +71,14 @@ namespace ReactiveUI.Tests var manualSave = new Subject(); var timesSaved = 0; - fixture.AutoPersist(x => - { - timesSaved++; - return Observables.Unit; - }, - manualSave, - TimeSpan.FromMilliseconds(100)); + fixture.AutoPersist( + _ => + { + timesSaved++; + return Observables.Unit; + }, + manualSave, + TimeSpan.FromMilliseconds(100)); // No changes = no saving sched.AdvanceByMs(2 * 100); @@ -110,13 +112,14 @@ namespace ReactiveUI.Tests var manualSave = new Subject(); var timesSaved = 0; - var disp = fixture.AutoPersist(x => - { - timesSaved++; - return Observables.Unit; - }, - manualSave, - TimeSpan.FromMilliseconds(100)); + var disp = fixture.AutoPersist( + _ => + { + timesSaved++; + return Observables.Unit; + }, + manualSave, + TimeSpan.FromMilliseconds(100)); // No changes = no saving sched.AdvanceByMs(2 * 100); @@ -155,13 +158,14 @@ namespace ReactiveUI.Tests var fixture = new ObservableCollectionExtended { item }; var timesSaved = 0; - fixture.AutoPersistCollection(x => - { - timesSaved++; - return Observables.Unit; - }, - manualSave, - TimeSpan.FromMilliseconds(100)); + fixture.AutoPersistCollection( + _ => + { + timesSaved++; + return Observables.Unit; + }, + manualSave, + TimeSpan.FromMilliseconds(100)); sched.AdvanceByMs(2 * 100); Assert.Equal(0, timesSaved); @@ -215,13 +219,14 @@ namespace ReactiveUI.Tests var fixture = new ObservableCollectionExtended { item }; var timesSaved = 0; - var disp = fixture.AutoPersistCollection(x => - { - timesSaved++; - return Observables.Unit; - }, - manualSave, - TimeSpan.FromMilliseconds(100)); + var disp = fixture.AutoPersistCollection( + _ => + { + timesSaved++; + return Observables.Unit; + }, + manualSave, + TimeSpan.FromMilliseconds(100)); sched.AdvanceByMs(2 * 100); Assert.Equal(0, timesSaved); diff --git a/src/ReactiveUI.Tests/AwaiterTest.cs b/src/ReactiveUI.Tests/AwaiterTest.cs index 55ba1b41..f3025426 100644 --- a/src/ReactiveUI.Tests/AwaiterTest.cs +++ b/src/ReactiveUI.Tests/AwaiterTest.cs @@ -26,11 +26,13 @@ namespace ReactiveUI.Tests private async Task AwaitAnObservable() { - var o = Observable.Start(() => - { - Thread.Sleep(1000); - return 42; - }, RxApp.TaskpoolScheduler); + var o = Observable.Start( + () => + { + Thread.Sleep(1000); + return 42; + }, + RxApp.TaskpoolScheduler); var ret = await o; return ret; diff --git a/src/ReactiveUI.Tests/ObservableAsPropertyHelperTest.cs b/src/ReactiveUI.Tests/ObservableAsPropertyHelperTest.cs index 45e3a7f0..e7b3b3bd 100755 --- a/src/ReactiveUI.Tests/ObservableAsPropertyHelperTest.cs +++ b/src/ReactiveUI.Tests/ObservableAsPropertyHelperTest.cs @@ -28,7 +28,8 @@ namespace ReactiveUI.Tests new TestScheduler().With(sched => { - var fixture = new ObservableAsPropertyHelper(input, + var fixture = new ObservableAsPropertyHelper( + input, x => output.Add(x), -5); @@ -50,7 +51,8 @@ namespace ReactiveUI.Tests new TestScheduler().With(sched => { - var fixture = new ObservableAsPropertyHelper(input, + var fixture = new ObservableAsPropertyHelper( + input, x => output.Add(x), 1); @@ -69,7 +71,8 @@ namespace ReactiveUI.Tests new TestScheduler().With(sched => { - var fixture = new ObservableAsPropertyHelper(Observable.Never, + var fixture = new ObservableAsPropertyHelper( + Observable.Never, x => output.Add(x), 32); @@ -83,7 +86,8 @@ namespace ReactiveUI.Tests var sched = new TestScheduler(); var input = new Subject(); - var fixture = new ObservableAsPropertyHelper(input, + var fixture = new ObservableAsPropertyHelper( + input, _ => { }, -5, scheduler: sched); diff --git a/src/ReactiveUI.Tests/ObservedChangedMixinTest.cs b/src/ReactiveUI.Tests/ObservedChangedMixinTest.cs index bef98f9b..fe95f65f 100755 --- a/src/ReactiveUI.Tests/ObservedChangedMixinTest.cs +++ b/src/ReactiveUI.Tests/ObservedChangedMixinTest.cs @@ -200,28 +200,31 @@ namespace ReactiveUI.Tests var canStart = Players.ToObservableChangeSet().CountChanged().Select(_ => Players.Count >= 3); StartGame = ReactiveCommand.Create(() => { }, canStart); - RandomizeOrder = ReactiveCommand.Create(() => - { - using (Players.SuspendNotifications()) - { - var r = new Random(); - var newOrder = Players.OrderBy(x => r.NextDouble()).ToList(); - Players.Clear(); - Players.AddRange(newOrder); - } - }, - canStart); + RandomizeOrder = ReactiveCommand.Create( + () => + { + using (Players.SuspendNotifications()) + { + var r = new Random(); + var newOrder = Players.OrderBy(x => r.NextDouble()).ToList(); + Players.Clear(); + Players.AddRange(newOrder); + } + }, + canStart); RemovePlayer = ReactiveCommand.Create(player => Players.Remove(player)); - var canAddPlayer = this.WhenAnyValue(x => x.Players.Count, - x => x.NewPlayerName, - (count, newPlayerName) => count < 7 && !string.IsNullOrWhiteSpace(newPlayerName) && !Players.Contains(newPlayerName)); - AddPlayer = ReactiveCommand.Create(() => - { - Players.Add(NewPlayerName.Trim()); - NewPlayerName = string.Empty; - }, - canAddPlayer); + var canAddPlayer = this.WhenAnyValue( + x => x.Players.Count, + x => x.NewPlayerName, + (count, newPlayerName) => count < 7 && !string.IsNullOrWhiteSpace(newPlayerName) && !Players.Contains(newPlayerName)); + AddPlayer = ReactiveCommand.Create( + () => + { + Players.Add(NewPlayerName.Trim()); + NewPlayerName = string.Empty; + }, + canAddPlayer); } public ObservableCollectionExtended Players { get; } diff --git a/src/ReactiveUI.Winforms/ActivationForViewFetcher.cs b/src/ReactiveUI.Winforms/ActivationForViewFetcher.cs index a78f5ed8..3042333a 100644 --- a/src/ReactiveUI.Winforms/ActivationForViewFetcher.cs +++ b/src/ReactiveUI.Winforms/ActivationForViewFetcher.cs @@ -62,17 +62,7 @@ namespace ReactiveUI.Winforms return Observable.Empty; } - private bool GetCachedIsDesignMode(Control control) - { - if (_isDesignModeCache == null) - { - _isDesignModeCache = GetIsDesignMode(control); - } - - return _isDesignModeCache.Value; - } - - private bool GetIsDesignMode(Control control) + private static bool GetIsDesignMode(Control control) { var isDesignMode = false; @@ -93,5 +83,15 @@ namespace ReactiveUI.Winforms return isDesignMode; } + + private bool GetCachedIsDesignMode(Control control) + { + if (_isDesignModeCache == null) + { + _isDesignModeCache = GetIsDesignMode(control); + } + + return _isDesignModeCache.Value; + } } } diff --git a/src/ReactiveUI.Winforms/CreatesCommandBinding.cs b/src/ReactiveUI.Winforms/CreatesWinformsCommandBinding.cs old mode 100755 new mode 100644 similarity index 100% rename from src/ReactiveUI.Winforms/CreatesCommandBinding.cs rename to src/ReactiveUI.Winforms/CreatesWinformsCommandBinding.cs diff --git a/src/ReactiveUI.Winforms/EventShims/PropertyChangedEventManager.cs b/src/ReactiveUI.Winforms/EventShims/PropertyChangedEventManager.cs new file mode 100644 index 00000000..e0240dfd --- /dev/null +++ b/src/ReactiveUI.Winforms/EventShims/PropertyChangedEventManager.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Diagnostics.CodeAnalysis; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ReactiveUI.Winforms +{ + [SuppressMessage("Design", "CA1812: Instance not created", Justification = "Created by static method in other assembly.")] + internal class PropertyChangedEventManager : WeakEventManager + { + } +} diff --git a/src/ReactiveUI.Winforms/EventShims/PropertyChangingEventManager.cs b/src/ReactiveUI.Winforms/EventShims/PropertyChangingEventManager.cs new file mode 100644 index 00000000..0ebeafad --- /dev/null +++ b/src/ReactiveUI.Winforms/EventShims/PropertyChangingEventManager.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ReactiveUI.Winforms +{ + [SuppressMessage("Design", "CA1812: Instance not created", Justification = "Created by static method in other assembly.")] + internal class PropertyChangingEventManager : WeakEventManager + { + } +} diff --git a/src/ReactiveUI.Winforms/IReactiveDerivedBindingList.cs b/src/ReactiveUI.Winforms/IReactiveDerivedBindingList.cs new file mode 100644 index 00000000..3c35c2b5 --- /dev/null +++ b/src/ReactiveUI.Winforms/IReactiveDerivedBindingList.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Diagnostics.CodeAnalysis; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using ReactiveUI.Legacy; + +namespace ReactiveUI.Winforms +{ + /// + /// IReactiveDerivedList represents a bindinglist whose contents will "follow" another + /// collection; this method is useful for creating ViewModel collections + /// that are automatically updated when the respective Model collection is updated. + /// + /// The type. + [Obsolete("ReactiveList is no longer supported. We suggest replacing it with DynamicData https://github.com/rolandpheasant/dynamicdata")] + [SuppressMessage("Design", "CA1010: IList inheritors should inherit the generic form", Justification = "Legacy code.")] + public interface IReactiveDerivedBindingList : IReactiveDerivedList, IBindingList + { + } +} diff --git a/src/ReactiveUI.Winforms/ReactiveDerivedBindingListMixins.cs b/src/ReactiveUI.Winforms/ObservableCollectionMixin.cs similarity index 64% rename from src/ReactiveUI.Winforms/ReactiveDerivedBindingListMixins.cs rename to src/ReactiveUI.Winforms/ObservableCollectionMixin.cs index 97f2eb71..95cb5e62 100644 --- a/src/ReactiveUI.Winforms/ReactiveDerivedBindingListMixins.cs +++ b/src/ReactiveUI.Winforms/ObservableCollectionMixin.cs @@ -1,110 +1,16 @@ -// 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; +using System; using System.Collections.Generic; -using System.Collections.Specialized; -using System.ComponentModel; using System.Diagnostics.Contracts; +using System.Linq; using System.Reactive; -using System.Reactive.Concurrency; using System.Reactive.Linq; -using ReactiveUI.Legacy; - namespace ReactiveUI.Winforms.Legacy { /// - /// IReactiveDerivedList represents a bindinglist whose contents will "follow" another - /// collection; this method is useful for creating ViewModel collections - /// that are automatically updated when the respective Model collection is updated. + /// A set of extension methods associated with the IReactiveDerivedBindingList{TNew}. /// - /// The type. [Obsolete("ReactiveList is no longer supported. We suggest replacing it with DynamicData https://github.com/rolandpheasant/dynamicdata")] - public interface IReactiveDerivedBindingList : IReactiveDerivedList, IBindingList - { - } - - [Obsolete("ReactiveList is no longer supported. We suggest replacing it with DynamicData https://github.com/rolandpheasant/dynamicdata")] - internal class ReactiveDerivedBindingList : - ReactiveDerivedCollection, IReactiveDerivedBindingList - { - public ReactiveDerivedBindingList( - IEnumerable source, - Func selector, - Func filter, - Func orderer, - Action removed, - IObservable signalReset) - : base(source, selector, filter, orderer, removed, signalReset, Scheduler.Immediate) - { - } - - protected override void RaiseCollectionChanged(NotifyCollectionChangedEventArgs e) - { - base.RaiseCollectionChanged(e); - if (ListChanged != null) - { - e.AsListChangedEventArgs().ForEach(x => ListChanged(this, x)); - } - } - - private const string ReadonlyExceptionMessage = "Derived collections cannot be modified."; - - public object AddNew() - { - throw new NotSupportedException(ReadonlyExceptionMessage); - } - - public void AddIndex(PropertyDescriptor property) - { - throw new NotSupportedException(); - } - - public void ApplySort(PropertyDescriptor property, ListSortDirection direction) - { - throw new NotSupportedException(); - } - - public int Find(PropertyDescriptor property, object key) - { - throw new NotSupportedException(); - } - - public void RemoveIndex(PropertyDescriptor property) - { - throw new NotSupportedException(); - } - - public void RemoveSort() - { - throw new NotSupportedException(); - } - - public bool AllowNew => false; - - public bool AllowEdit => false; - - public bool AllowRemove => false; - - public bool SupportsChangeNotification => true; - - public bool SupportsSearching => false; - - public bool SupportsSorting => false; - - public bool IsSorted => false; - - public PropertyDescriptor SortProperty => null; - - public ListSortDirection SortDirection => ListSortDirection.Ascending; - - public event ListChangedEventHandler ListChanged; - } - - [Obsolete("ReactiveList is no longer supported. We suggest replacing it with DynamicData https://github.com/rolandpheasant/dynamicdata")] -#pragma warning disable SA1600 // Elements should be documented public static class ObservableCollectionMixin { /// @@ -122,6 +28,7 @@ namespace ReactiveUI.Winforms.Legacy /// The type. /// The new type. /// The signal type. + /// The collection we are creating a derived list from. /// A Select function that will be run on each /// item. /// An action that is called on each item when @@ -133,12 +40,11 @@ namespace ReactiveUI.Winforms.Legacy /// When this Observable is signalled, /// the derived collection will be manually /// reordered/refiltered. - /// The source collection to follow. /// A new collection whose items are equivalent to /// Collection.Select().Where().OrderBy() and will mirror changes /// in the initial collection. public static IReactiveDerivedBindingList CreateDerivedBindingList( - this IEnumerable @this, + this IEnumerable collection, Func selector, Action removed, Func filter = null, @@ -154,7 +60,7 @@ namespace ReactiveUI.Winforms.Legacy reset = signalReset.Select(_ => Unit.Default); } - return new ReactiveDerivedBindingList(@this, selector, filter, orderer, removed, reset); + return new ReactiveDerivedBindingList(collection, selector, filter, orderer, removed, reset); } /// @@ -172,6 +78,7 @@ namespace ReactiveUI.Winforms.Legacy /// The type. /// The new type. /// The signal type. + /// The collection we are creating a derived list from. /// A Select function that will be run on each /// item. /// A filter to determine whether to exclude items @@ -181,18 +88,17 @@ namespace ReactiveUI.Winforms.Legacy /// When this Observable is signalled, /// the derived collection will be manually /// reordered/refiltered. - /// The source collection to follow. /// A new collection whose items are equivalent to /// Collection.Select().Where().OrderBy() and will mirror changes /// in the initial collection. public static IReactiveDerivedBindingList CreateDerivedBindingList( - this IEnumerable @this, + this IEnumerable collection, Func selector, Func filter = null, Func orderer = null, IObservable signalReset = null) { - return @this.CreateDerivedBindingList(selector, null, filter, orderer, signalReset); + return collection.CreateDerivedBindingList(selector, null, filter, orderer, signalReset); } /// @@ -208,6 +114,7 @@ namespace ReactiveUI.Winforms.Legacy /// /// The type. /// The new type. + /// The collection we are creating a derived list from. /// A Select function that will be run on each /// item. /// An action that is called on each item when @@ -216,18 +123,17 @@ namespace ReactiveUI.Winforms.Legacy /// in the derived collection. /// A comparator method to determine the ordering of /// the resulting collection. - /// The source collection to follow. /// A new collection whose items are equivalent to /// Collection.Select().Where().OrderBy() and will mirror changes /// in the initial collection. public static IReactiveDerivedBindingList CreateDerivedBindingList( - this IEnumerable @this, + this IEnumerable collection, Func selector, Action removed, Func filter = null, Func orderer = null) { - return @this.CreateDerivedBindingList(selector, removed, filter, orderer, (IObservable)null); + return collection.CreateDerivedBindingList(selector, removed, filter, orderer, (IObservable)null); } /// @@ -243,25 +149,23 @@ namespace ReactiveUI.Winforms.Legacy /// /// The type. /// The new type. + /// The collection we are creating a derived list from. /// A Select function that will be run on each /// item. /// A filter to determine whether to exclude items /// in the derived collection. /// A comparator method to determine the ordering of /// the resulting collection. - /// The source collection to follow. /// A new collection whose items are equivalent to /// Collection.Select().Where().OrderBy() and will mirror changes /// in the initial collection. public static IReactiveDerivedBindingList CreateDerivedBindingList( - this IEnumerable @this, + this IEnumerable collection, Func selector, Func filter = null, Func orderer = null) { - return @this.CreateDerivedBindingList(selector, null, filter, orderer, (IObservable)null); + return collection.CreateDerivedBindingList(selector, null, filter, orderer, (IObservable)null); } } - -#pragma warning restore SA1600 // Elements should be documented } diff --git a/src/ReactiveUI.Winforms/ReactiveBindingList.cs b/src/ReactiveUI.Winforms/ReactiveBindingList.cs index 30123320..eb4c99e1 100644 --- a/src/ReactiveUI.Winforms/ReactiveBindingList.cs +++ b/src/ReactiveUI.Winforms/ReactiveBindingList.cs @@ -12,18 +12,63 @@ using ReactiveUI.Legacy; namespace ReactiveUI.Winforms.Legacy { + /// + /// A version of the ReactiveList that works with the Winforms IBindingList. + /// + /// The type of item in the list. [Obsolete("ReactiveList is no longer supported. We suggest replacing it with DynamicData https://github.com/rolandpheasant/dynamicdata")] -#pragma warning disable SA1600 // Elements should be documented - public class ReactiveBindingList : ReactiveList, - IList, ICollection, IEnumerable, - ICollection, IEnumerable, IList, IBindingList, - ICancelAddNew, IRaiseItemChangedEvents + public class ReactiveBindingList : ReactiveList, IBindingList, ICancelAddNew, IRaiseItemChangedEvents { + /// + /// Initializes a new instance of the class. + /// public ReactiveBindingList() : this(null) { } + /// + /// Initializes a new instance of the class. + /// + /// The items. + public ReactiveBindingList(IEnumerable items) + : base(items) + { + } + + /// + public event ListChangedEventHandler ListChanged; + + /// + public bool RaisesItemChangedEvents => ChangeTrackingEnabled; + + /// + public bool AllowNew => true; + + /// + public bool AllowEdit => true; + + /// + public bool AllowRemove => true; + + /// + public bool SupportsChangeNotification => true; + + /// + public bool SupportsSearching => false; + + /// + public bool SupportsSorting => false; + + /// + public bool IsSorted => false; + + /// + public PropertyDescriptor SortProperty => null; + + /// + public ListSortDirection SortDirection => ListSortDirection.Ascending; + /// public void CancelNew(int itemIndex) { @@ -36,28 +81,6 @@ namespace ReactiveUI.Winforms.Legacy // throw new NotImplementedException(); } - /// - public bool RaisesItemChangedEvents => ChangeTrackingEnabled; - - /// - /// ReactiveBindingList constructor. - /// - /// The items. - public ReactiveBindingList(IEnumerable items) - : base(items) - { - } - - /// - protected override void RaiseCollectionChanged(NotifyCollectionChangedEventArgs e) - { - base.RaiseCollectionChanged(e); - if (ListChanged != null) - { - e.AsListChangedEventArgs().ForEach(x => ListChanged(this, x)); - } - } - /// public object AddNew() { @@ -95,34 +118,13 @@ namespace ReactiveUI.Winforms.Legacy } /// - public bool AllowNew => true; - - /// - public bool AllowEdit => true; - - /// - public bool AllowRemove => true; - - /// - public bool SupportsChangeNotification => true; - - /// - public bool SupportsSearching => false; - - /// - public bool SupportsSorting => false; - - /// - public bool IsSorted => false; - - /// - public PropertyDescriptor SortProperty => null; - - /// - public ListSortDirection SortDirection => ListSortDirection.Ascending; - - /// - public event ListChangedEventHandler ListChanged; + protected override void RaiseCollectionChanged(NotifyCollectionChangedEventArgs e) + { + base.RaiseCollectionChanged(e); + if (ListChanged != null) + { + e.AsListChangedEventArgs().ForEach(x => ListChanged(this, x)); + } + } } -#pragma warning restore SA1600 // Elements should be documented } diff --git a/src/ReactiveUI.Winforms/ReactiveDerivedBindingList.cs b/src/ReactiveUI.Winforms/ReactiveDerivedBindingList.cs new file mode 100644 index 00000000..b86c3b55 --- /dev/null +++ b/src/ReactiveUI.Winforms/ReactiveDerivedBindingList.cs @@ -0,0 +1,93 @@ +// 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; +using System.Collections.Generic; +using System.Collections.Specialized; +using System.ComponentModel; +using System.Diagnostics.Contracts; +using System.Reactive; +using System.Reactive.Concurrency; +using System.Reactive.Linq; + +using ReactiveUI.Legacy; + +namespace ReactiveUI.Winforms.Legacy +{ + [Obsolete("ReactiveList is no longer supported. We suggest replacing it with DynamicData https://github.com/rolandpheasant/dynamicdata")] + internal class ReactiveDerivedBindingList : ReactiveDerivedCollection, IReactiveDerivedBindingList + { + private const string ReadonlyExceptionMessage = "Derived collections cannot be modified."; + + public ReactiveDerivedBindingList( + IEnumerable source, + Func selector, + Func filter, + Func orderer, + Action removed, + IObservable signalReset) + : base(source, selector, filter, orderer, removed, signalReset, Scheduler.Immediate) + { + } + + public event ListChangedEventHandler ListChanged; + + public bool AllowNew => false; + + public bool AllowEdit => false; + + public bool AllowRemove => false; + + public bool SupportsChangeNotification => true; + + public bool SupportsSearching => false; + + public bool SupportsSorting => false; + + public bool IsSorted => false; + + public PropertyDescriptor SortProperty => null; + + public ListSortDirection SortDirection => ListSortDirection.Ascending; + + public object AddNew() + { + throw new NotSupportedException(ReadonlyExceptionMessage); + } + + public void AddIndex(PropertyDescriptor property) + { + throw new NotSupportedException(); + } + + public void ApplySort(PropertyDescriptor property, ListSortDirection direction) + { + throw new NotSupportedException(); + } + + public int Find(PropertyDescriptor property, object key) + { + throw new NotSupportedException(); + } + + public void RemoveIndex(PropertyDescriptor property) + { + throw new NotSupportedException(); + } + + public void RemoveSort() + { + throw new NotSupportedException(); + } + + protected override void RaiseCollectionChanged(NotifyCollectionChangedEventArgs e) + { + base.RaiseCollectionChanged(e); + if (ListChanged != null) + { + e.AsListChangedEventArgs().ForEach(x => ListChanged(this, x)); + } + } + } +} diff --git a/src/ReactiveUI.Winforms/RoutedViewHost.cs b/src/ReactiveUI.Winforms/RoutedViewHost.cs index 50ad0ae5..edb719b6 100644 --- a/src/ReactiveUI.Winforms/RoutedViewHost.cs +++ b/src/ReactiveUI.Winforms/RoutedViewHost.cs @@ -10,6 +10,9 @@ using System.Windows.Forms; namespace ReactiveUI.Winforms { + /// + /// A control host which will handling routing between different ViewModels and Views. + /// [DefaultProperty("ViewModel")] public partial class RoutedControlHost : UserControl, IReactiveObject { @@ -156,7 +159,7 @@ namespace ReactiveUI.Winforms base.Dispose(disposing); } - private Control InitView(Control view) + private static Control InitView(Control view) { view.Dock = DockStyle.Fill; return view; diff --git a/src/ReactiveUI.Winforms/ViewModelViewHost.cs b/src/ReactiveUI.Winforms/ViewModelViewHost.cs index b7db3d3d..a91cb824 100644 --- a/src/ReactiveUI.Winforms/ViewModelViewHost.cs +++ b/src/ReactiveUI.Winforms/ViewModelViewHost.cs @@ -11,6 +11,9 @@ using System.Windows.Forms; namespace ReactiveUI.Winforms { + /// + /// A view model control host which will find and host the View for a ViewModel. + /// [DefaultProperty("ViewModel")] public partial class ViewModelControlHost : UserControl, IReactiveObject, IViewFor { @@ -18,11 +21,8 @@ namespace ReactiveUI.Winforms private Control _defaultContent; private IObservable _viewContractObservable; private object _viewModel; - - /// - /// Gets or sets a value indicating whether [default cache views enabled]. - /// - public static bool DefaultCacheViewsEnabled { get; set; } + private object _content; + private bool _cacheViews; /// /// Initializes a new instance of the class. @@ -52,6 +52,11 @@ namespace ReactiveUI.Winforms remove => PropertyChangedEventManager.RemoveHandler(this, value); } + /// + /// Gets or sets a value indicating whether [default cache views enabled]. + /// + public static bool DefaultCacheViewsEnabled { get; set; } + /// /// Gets the current view. /// @@ -97,8 +102,6 @@ namespace ReactiveUI.Winforms set => this.RaiseAndSetIfChanged(ref _viewModel, value); } - private object _content; - /// /// Gets or sets the content. /// @@ -111,8 +114,6 @@ namespace ReactiveUI.Winforms protected set => this.RaiseAndSetIfChanged(ref _content, value); } - private bool _cacheViews; - /// /// Gets or sets a value indicating whether to cache views. /// diff --git a/src/ReactiveUI.Winforms/WeakEventManagerShims.cs b/src/ReactiveUI.Winforms/WeakEventManagerShims.cs deleted file mode 100644 index 7e0987b7..00000000 --- a/src/ReactiveUI.Winforms/WeakEventManagerShims.cs +++ /dev/null @@ -1,35 +0,0 @@ -// 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; -using System.Collections.Generic; -using System.Collections.Specialized; -using System.ComponentModel; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows.Input; - -namespace ReactiveUI.Winforms -{ - internal class CanExecuteChangedEventManager : WeakEventManager - { - } - - internal class PropertyChangingEventManager : WeakEventManager - { - } - - internal class PropertyChangedEventManager : WeakEventManager - { - } - - internal class CollectionChangingEventManager : WeakEventManager - { - } - - internal class CollectionChangedEventManager : WeakEventManager - { - } -} diff --git a/src/ReactiveUI.Wpf/WpfAutoSuspendHelper.cs b/src/ReactiveUI.Wpf/AutoSuspendHelper.cs similarity index 100% rename from src/ReactiveUI.Wpf/WpfAutoSuspendHelper.cs rename to src/ReactiveUI.Wpf/AutoSuspendHelper.cs index a84c600a..32d1b892 100644 --- a/src/ReactiveUI.Wpf/WpfAutoSuspendHelper.cs +++ b/src/ReactiveUI.Wpf/AutoSuspendHelper.cs @@ -24,11 +24,6 @@ namespace ReactiveUI /// public class AutoSuspendHelper : IEnableLogger { - /// - /// Gets or sets the time out before the Auto Suspension happens. - /// - public TimeSpan IdleTimeout { get; set; } - /// /// Initializes a new instance of the class. /// @@ -69,5 +64,10 @@ namespace ReactiveUI AppDomain.CurrentDomain.UnhandledException += (o, e) => untimelyDeath.OnNext(Unit.Default); RxApp.SuspensionHost.ShouldInvalidateState = untimelyDeath; } + + /// + /// Gets or sets the time out before the Auto Suspension happens. + /// + public TimeSpan IdleTimeout { get; set; } } } diff --git a/src/ReactiveUI.Wpf/WpfDependencyObjectObservableForProperty.cs b/src/ReactiveUI.Wpf/DependencyObjectObservableForProperty.cs similarity index 96% rename from src/ReactiveUI.Wpf/WpfDependencyObjectObservableForProperty.cs rename to src/ReactiveUI.Wpf/DependencyObjectObservableForProperty.cs index 49125b72..55aef44f 100644 --- a/src/ReactiveUI.Wpf/WpfDependencyObjectObservableForProperty.cs +++ b/src/ReactiveUI.Wpf/DependencyObjectObservableForProperty.cs @@ -56,7 +56,7 @@ namespace ReactiveUI }); } - private DependencyProperty GetDependencyProperty(Type type, string propertyName) + private static DependencyProperty GetDependencyProperty(Type type, string propertyName) { var fi = type.GetTypeInfo().GetFields(BindingFlags.FlattenHierarchy | BindingFlags.Static | BindingFlags.Public) .FirstOrDefault(x => x.Name == propertyName + "Property" && x.IsStatic); diff --git a/src/ReactiveUI.Wpf/ReactiveUI.Wpf.csproj b/src/ReactiveUI.Wpf/ReactiveUI.Wpf.csproj index c72ade75..eb92fc10 100644 --- a/src/ReactiveUI.Wpf/ReactiveUI.Wpf.csproj +++ b/src/ReactiveUI.Wpf/ReactiveUI.Wpf.csproj @@ -10,4 +10,8 @@ + + + + diff --git a/src/ReactiveUI.Wpf/ReactiveWindow.cs b/src/ReactiveUI.Wpf/ReactiveWindow.cs index 9f00f6d0..c2704d86 100644 --- a/src/ReactiveUI.Wpf/ReactiveWindow.cs +++ b/src/ReactiveUI.Wpf/ReactiveWindow.cs @@ -38,11 +38,6 @@ namespace ReactiveUI Window, IViewFor where TViewModel : class { - /// - /// Gets the binding root view model. - /// - public TViewModel BindingRoot => ViewModel; - /// /// The view model dependency property. /// @@ -53,6 +48,11 @@ namespace ReactiveUI typeof(ReactiveWindow), new PropertyMetadata(null)); + /// + /// Gets the binding root view model. + /// + public TViewModel BindingRoot => ViewModel; + /// public TViewModel ViewModel { diff --git a/src/ReactiveUI.Wpf/TransitioningContentControl.cs b/src/ReactiveUI.Wpf/TransitioningContentControl.cs index b757296e..267a9bec 100644 --- a/src/ReactiveUI.Wpf/TransitioningContentControl.cs +++ b/src/ReactiveUI.Wpf/TransitioningContentControl.cs @@ -159,6 +159,31 @@ namespace ReactiveUI } } + /// + public override void OnApplyTemplate() + { + // Wire up all of the various control parts. + _container = (Grid)GetTemplateChild("PART_Container"); + if (_container == null) + { + throw new ArgumentException("PART_Container not found."); + } + + _currentContentPresentationSite = + (ContentPresenter)GetTemplateChild("PART_CurrentContentPresentationSite"); + if (_currentContentPresentationSite == null) + { + throw new ArgumentException("PART_CurrentContentPresentationSite not found."); + } + + _previousContentPresentationSite = + (ContentPresenter)GetTemplateChild("PART_PreviousContentPresentationSite"); + + // Set the current content site to the first piece of content. + _currentContentPresentationSite.Content = Content; + VisualStateManager.GoToState(this, NormalState, false); + } + /// /// Called when the value of the property changes. /// @@ -308,31 +333,6 @@ namespace ReactiveUI return transition; } - /// - public override void OnApplyTemplate() - { - // Wire up all of the various control parts. - _container = (Grid)GetTemplateChild("PART_Container"); - if (_container == null) - { - throw new ArgumentException("PART_Container not found."); - } - - _currentContentPresentationSite = - (ContentPresenter)GetTemplateChild("PART_CurrentContentPresentationSite"); - if (_currentContentPresentationSite == null) - { - throw new ArgumentException("PART_CurrentContentPresentationSite not found."); - } - - _previousContentPresentationSite = - (ContentPresenter)GetTemplateChild("PART_PreviousContentPresentationSite"); - - // Set the current content site to the first piece of content. - _currentContentPresentationSite.Content = Content; - VisualStateManager.GoToState(this, NormalState, false); - } - /// /// Sets default values for certain transition types. /// diff --git a/src/ReactiveUI.XamForms/DisableAnimationAttribute.cs b/src/ReactiveUI.XamForms/DisableAnimationAttribute.cs index 9a9b161c..96852909 100644 --- a/src/ReactiveUI.XamForms/DisableAnimationAttribute.cs +++ b/src/ReactiveUI.XamForms/DisableAnimationAttribute.cs @@ -6,6 +6,7 @@ namespace ReactiveUI.XamForms /// Attribute that diables animation for a view. /// /// + [AttributeUsage(AttributeTargets.All)] public class DisableAnimationAttribute : Attribute { } diff --git a/src/ReactiveUI.XamForms/ReactiveCarouselPage.cs b/src/ReactiveUI.XamForms/ReactiveCarouselPage.cs index 778f0e26..c2209799 100644 --- a/src/ReactiveUI.XamForms/ReactiveCarouselPage.cs +++ b/src/ReactiveUI.XamForms/ReactiveCarouselPage.cs @@ -29,7 +29,7 @@ namespace ReactiveUI.XamForms propertyChanged: OnViewModelChanged); /// - /// The ViewModel to display. + /// Gets or sets the ViewModel to display. /// public TViewModel ViewModel { diff --git a/src/ReactiveUI.XamForms/ReactiveContentPage.cs b/src/ReactiveUI.XamForms/ReactiveContentPage.cs index 0ededec0..d4bdd06c 100644 --- a/src/ReactiveUI.XamForms/ReactiveContentPage.cs +++ b/src/ReactiveUI.XamForms/ReactiveContentPage.cs @@ -29,7 +29,7 @@ namespace ReactiveUI.XamForms propertyChanged: OnViewModelChanged); /// - /// The ViewModel to display. + /// Gets or sets the ViewModel to display. /// public TViewModel ViewModel { diff --git a/src/ReactiveUI.XamForms/ReactiveContentView.cs b/src/ReactiveUI.XamForms/ReactiveContentView.cs index 6dd1c8a6..c54ea1fd 100644 --- a/src/ReactiveUI.XamForms/ReactiveContentView.cs +++ b/src/ReactiveUI.XamForms/ReactiveContentView.cs @@ -29,7 +29,7 @@ namespace ReactiveUI.XamForms propertyChanged: OnViewModelChanged); /// - /// The ViewModel to display. + /// Gets or sets the ViewModel to display. /// public TViewModel ViewModel { diff --git a/src/ReactiveUI.XamForms/ReactiveMasterDetailPage.cs b/src/ReactiveUI.XamForms/ReactiveMasterDetailPage.cs index 0e2a511c..69476b1b 100644 --- a/src/ReactiveUI.XamForms/ReactiveMasterDetailPage.cs +++ b/src/ReactiveUI.XamForms/ReactiveMasterDetailPage.cs @@ -29,7 +29,7 @@ namespace ReactiveUI.XamForms propertyChanged: OnViewModelChanged); /// - /// The ViewModel to display. + /// Gets or sets the ViewModel to display. /// public TViewModel ViewModel { diff --git a/src/ReactiveUI.XamForms/ReactiveMultiPage.cs b/src/ReactiveUI.XamForms/ReactiveMultiPage.cs index 1bb94535..5637ce0c 100644 --- a/src/ReactiveUI.XamForms/ReactiveMultiPage.cs +++ b/src/ReactiveUI.XamForms/ReactiveMultiPage.cs @@ -31,7 +31,7 @@ namespace ReactiveUI.XamForms propertyChanged: OnViewModelChanged); /// - /// The ViewModel to display. + /// Gets or sets the ViewModel to display. /// public TViewModel ViewModel { diff --git a/src/ReactiveUI.XamForms/ReactiveNavigationPage.cs b/src/ReactiveUI.XamForms/ReactiveNavigationPage.cs index 610f8278..c19cb85f 100644 --- a/src/ReactiveUI.XamForms/ReactiveNavigationPage.cs +++ b/src/ReactiveUI.XamForms/ReactiveNavigationPage.cs @@ -29,7 +29,7 @@ namespace ReactiveUI.XamForms propertyChanged: OnViewModelChanged); /// - /// The ViewModel to display. + /// Gets or sets the ViewModel to display. /// public TViewModel ViewModel { diff --git a/src/ReactiveUI.XamForms/ReactiveTabbedPage.cs b/src/ReactiveUI.XamForms/ReactiveTabbedPage.cs index 5db54f0f..e18c8d87 100644 --- a/src/ReactiveUI.XamForms/ReactiveTabbedPage.cs +++ b/src/ReactiveUI.XamForms/ReactiveTabbedPage.cs @@ -29,7 +29,7 @@ namespace ReactiveUI.XamForms propertyChanged: OnViewModelChanged); /// - /// The ViewModel to display. + /// Gets or sets the ViewModel to display. /// public TViewModel ViewModel { diff --git a/src/ReactiveUI.XamForms/RoutedViewHost.cs b/src/ReactiveUI.XamForms/RoutedViewHost.cs index 1c864ab0..b4154aa9 100644 --- a/src/ReactiveUI.XamForms/RoutedViewHost.cs +++ b/src/ReactiveUI.XamForms/RoutedViewHost.cs @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information. using System; +using System.Diagnostics.CodeAnalysis; using System.Reactive; using System.Reactive.Linq; using System.Reactive.Threading.Tasks; @@ -185,6 +186,7 @@ namespace ReactiveUI.XamForms /// /// The vm. /// An observable of the page associated to a . + [SuppressMessage("Design", "CA1822: Can be made static", Justification = "Might be used by implementors.")] protected IObservable PageForViewModel(IRoutableViewModel vm) { if (vm == null) diff --git a/src/ReactiveUI.XamForms/ViewModelViewHost.cs b/src/ReactiveUI.XamForms/ViewModelViewHost.cs index dd2fe9dd..57054907 100644 --- a/src/ReactiveUI.XamForms/ViewModelViewHost.cs +++ b/src/ReactiveUI.XamForms/ViewModelViewHost.cs @@ -104,7 +104,7 @@ namespace ReactiveUI.XamForms } /// - /// The view model whose associated view is to be displayed. + /// Gets or sets the view model whose associated view is to be displayed. /// public object ViewModel { @@ -113,7 +113,7 @@ namespace ReactiveUI.XamForms } /// - /// The content to display when is . + /// Gets or sets the content to display when is . /// public View DefaultContent { @@ -122,7 +122,7 @@ namespace ReactiveUI.XamForms } /// - /// The contract to use when resolving the view for the given view model. + /// Gets or sets the observable which signals when the contract to use when resolving the view for the given view model has changed. /// public IObservable ViewContractObservable { @@ -131,7 +131,7 @@ namespace ReactiveUI.XamForms } /// - /// A fixed contract to use when resolving the view for the given view model. + /// Gets or sets the fixed contract to use when resolving the view for the given view model. /// /// /// This property is a mere convenience so that a fixed contract can be assigned directly in XAML. @@ -143,7 +143,7 @@ namespace ReactiveUI.XamForms } /// - /// Can be used to override the view locator to use when resolving the view. If unspecified, will be used. + /// Gets or sets the override for the view locator to use when resolving the view. If unspecified, will be used. /// public IViewLocator ViewLocator { get; set; } } diff --git a/src/ReactiveUI.sln b/src/ReactiveUI.sln index e2387980..207b8991 100644 --- a/src/ReactiveUI.sln +++ b/src/ReactiveUI.sln @@ -9,9 +9,9 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Directory.build.props = Directory.build.props Directory.build.targets = Directory.build.targets global.json = global.json - ..\reactiveui.ruleset = ..\reactiveui.ruleset - ..\stylecop.json = ..\stylecop.json + reactiveui.ruleset = reactiveui.ruleset reactiveui.tests.ruleset = reactiveui.tests.ruleset + ..\stylecop.json = ..\stylecop.json EndProjectSection EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ReactiveUI", "ReactiveUI\ReactiveUI.csproj", "{464CB812-F99F-401B-BE4C-E8F0515CD19D}" diff --git a/src/ReactiveUI/Activation/ViewModelActivator.cs b/src/ReactiveUI/Activation/ViewModelActivator.cs index a83fb6a9..303aedd5 100644 --- a/src/ReactiveUI/Activation/ViewModelActivator.cs +++ b/src/ReactiveUI/Activation/ViewModelActivator.cs @@ -108,6 +108,11 @@ namespace ReactiveUI _deactivated?.Dispose(); } + /// + /// Adds a action blocks to the list of registered blocks. These will called + /// on activation, then disposed on deactivation. + /// + /// The block to add. internal void AddActivationBlock(Func> block) { _blocks.Add(block); diff --git a/src/ReactiveUI/Bindings/Command/RelayCommand.cs b/src/ReactiveUI/Bindings/Command/RelayCommand.cs index 38a92557..343d4864 100644 --- a/src/ReactiveUI/Bindings/Command/RelayCommand.cs +++ b/src/ReactiveUI/Bindings/Command/RelayCommand.cs @@ -13,6 +13,9 @@ using Splat; namespace ReactiveUI { + /// + /// Internal relay command used for Command binding. + /// internal class RelayCommand : ICommand { private readonly Func _canExecute; diff --git a/src/ReactiveUI/Bindings/Reactive/IReactiveBinding.cs b/src/ReactiveUI/Bindings/Reactive/IReactiveBinding.cs index f42fa37d..04af8c8e 100644 --- a/src/ReactiveUI/Bindings/Reactive/IReactiveBinding.cs +++ b/src/ReactiveUI/Bindings/Reactive/IReactiveBinding.cs @@ -21,55 +21,37 @@ namespace ReactiveUI where TView : IViewFor { /// - /// The instance of the view model this binding is applied to. + /// Gets the instance of the view model this binding is applied to. /// - /// - /// The view model. - /// TViewModel ViewModel { get; } /// - /// An expression representing the propertyon the viewmodel bound to the view. + /// Gets an expression representing the propertyon the viewmodel bound to the view. /// This can be a child property, for example x.Foo.Bar.Baz in which case /// that will be the expression. /// - /// - /// The expression. - /// Expression ViewModelExpression { get; } /// - /// The instance of the view this binding is applied to. + /// Gets the instance of the view this binding is applied to. /// - /// - /// The view. - /// TView View { get; } /// - /// An expression representing the property on the view bound to the viewmodel. + /// Gets an expression representing the property on the view bound to the viewmodel. /// This can be a child property, for example x.Foo.Bar.Baz in which case /// that will be the expression. /// - /// - /// The expression. - /// Expression ViewExpression { get; } /// - /// An observable representing changed values for the binding. + /// Gets an observable representing changed values for the binding. /// - /// - /// The changed. - /// IObservable Changed { get; } /// /// Gets the direction of the binding. /// - /// - /// The direction. - /// BindingDirection Direction { get; } } } diff --git a/src/ReactiveUI/Bindings/Reactive/ReactiveBinding.cs b/src/ReactiveUI/Bindings/Reactive/ReactiveBinding.cs index e7326e86..2b906fc2 100644 --- a/src/ReactiveUI/Bindings/Reactive/ReactiveBinding.cs +++ b/src/ReactiveUI/Bindings/Reactive/ReactiveBinding.cs @@ -32,56 +32,22 @@ namespace ReactiveUI _bindingDisposable = bindingDisposable; } - /// - /// The instance of the view model this binding is applied to. - /// - /// - /// The view model. - /// + /// public TViewModel ViewModel { get; private set; } - /// - /// An expression representing the propertyon the viewmodel bound to the view. - /// This can be a child property, for example x.Foo.Bar.Baz in which case - /// that will be the expression. - /// - /// - /// The expression. - /// + /// public Expression ViewModelExpression { get; private set; } - /// - /// The instance of the view this binding is applied to. - /// - /// - /// The view. - /// + /// public TView View { get; private set; } - /// - /// An expression representing the property on the view bound to the viewmodel. - /// This can be a child property, for example x.Foo.Bar.Baz in which case - /// that will be the expression. - /// - /// - /// The expression. - /// + /// public Expression ViewExpression { get; private set; } - /// - /// An observable representing changed values for the binding. - /// - /// - /// The changed. - /// + /// public IObservable Changed { get; private set; } - /// - /// Gets the direction of the binding. - /// - /// - /// The direction. - /// + /// public BindingDirection Direction { get; private set; } /// @@ -91,6 +57,10 @@ namespace ReactiveUI GC.SuppressFinalize(this); } + /// + /// Disposes of resources inside the class. + /// + /// If we are disposing managed resources. protected virtual void Dispose(bool isDisposing) { if (isDisposing) diff --git a/src/ReactiveUI/Comparers/OrderedComparer.cs b/src/ReactiveUI/Comparers/OrderedComparer.cs index f963ad85..27ae3775 100644 --- a/src/ReactiveUI/Comparers/OrderedComparer.cs +++ b/src/ReactiveUI/Comparers/OrderedComparer.cs @@ -15,6 +15,7 @@ namespace ReactiveUI /// If the type you're creating a comparer for is known this class is nothing more than an alias for the generic /// OrderedComparer. This class can be used to create comparers for anonymous types. /// + [SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:FileMayOnlyContainASingleType", Justification = "Classes with the same class names within.")] public static class OrderedComparer { /// @@ -70,13 +71,12 @@ namespace ReactiveUI } } -#pragma warning disable SA1402 // File may only contain a single type /// /// Convenience class providing a starting point for chaining comparers. /// /// The comparison type. + [SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:FileMayOnlyContainASingleType", Justification = "Classes with the same class names within.")] public static class OrderedComparer -#pragma warning restore SA1402 // File may only contain a single type { /// /// Creates a comparer that will sort elements in ascending order based on the values returned by the provided diff --git a/src/ReactiveUI/EventHandlers/LocalizableAttribute.cs b/src/ReactiveUI/EventHandlers/LocalizableAttribute.cs index 86f6fdd8..30df219b 100644 --- a/src/ReactiveUI/EventHandlers/LocalizableAttribute.cs +++ b/src/ReactiveUI/EventHandlers/LocalizableAttribute.cs @@ -15,12 +15,18 @@ namespace ReactiveUI public sealed class LocalizableAttribute : Attribute { /// - /// Initializes a new instance of the LocalizableAttribute class. + /// Initializes a new instance of the class. /// /// If the target is localizable or not. public LocalizableAttribute(bool isLocalizable) { + IsLocalizable = isLocalizable; } + + /// + /// Gets a value indicating whether the target is localizable. + /// + public bool IsLocalizable { get; } } } #endif diff --git a/src/ReactiveUI/EventHandlers/PropertyChangingEventHandler.cs b/src/ReactiveUI/EventHandlers/PropertyChangingEventHandler.cs index 5c743208..a221f7cc 100644 --- a/src/ReactiveUI/EventHandlers/PropertyChangingEventHandler.cs +++ b/src/ReactiveUI/EventHandlers/PropertyChangingEventHandler.cs @@ -4,7 +4,11 @@ namespace ReactiveUI { - public delegate void PropertyChangingEventHandler( - object sender, - PropertyChangingEventArgs e); -} \ No newline at end of file + /// + /// Event handler for the property changing events. + /// This will be called before a property value has changed. + /// + /// The sender of the event. + /// Details about the changing property. + public delegate void PropertyChangingEventHandler(object sender, PropertyChangingEventArgs e); +} diff --git a/src/ReactiveUI/Expression/ExpressionRewriter.cs b/src/ReactiveUI/Expression/ExpressionRewriter.cs index 7b1f3190..dc8fd8d7 100644 --- a/src/ReactiveUI/Expression/ExpressionRewriter.cs +++ b/src/ReactiveUI/Expression/ExpressionRewriter.cs @@ -12,6 +12,9 @@ using System.Threading.Tasks; namespace ReactiveUI { + /// + /// Class for simplifying and validating expressions. + /// internal class ExpressionRewriter : ExpressionVisitor { public override Expression Visit(Expression node) diff --git a/src/ReactiveUI/Interactions/Interaction.cs b/src/ReactiveUI/Interactions/Interaction.cs index 866446b9..e02ed765 100644 --- a/src/ReactiveUI/Interactions/Interaction.cs +++ b/src/ReactiveUI/Interactions/Interaction.cs @@ -54,7 +54,7 @@ namespace ReactiveUI private readonly IScheduler _handlerScheduler; /// - /// Creates a new interaction instance. + /// Initializes a new instance of the class. /// /// /// The scheduler to use when invoking handlers, which defaults to CurrentThreadScheduler.Instance if . diff --git a/src/ReactiveUI/Interfaces/IHandleObservableErrors.cs b/src/ReactiveUI/Interfaces/IHandleObservableErrors.cs index 886e6b20..c71ce992 100644 --- a/src/ReactiveUI/Interfaces/IHandleObservableErrors.cs +++ b/src/ReactiveUI/Interfaces/IHandleObservableErrors.cs @@ -20,7 +20,7 @@ namespace ReactiveUI public interface IHandleObservableErrors { /// - /// Fires whenever an exception would normally terminate ReactiveUI + /// Gets a observable which will fire whenever an exception would normally terminate ReactiveUI /// internal state. /// IObservable ThrownExceptions { get; } diff --git a/src/ReactiveUI/Interfaces/IObservedChange.cs b/src/ReactiveUI/Interfaces/IObservedChange.cs index 195e26cc..8033a2c7 100644 --- a/src/ReactiveUI/Interfaces/IObservedChange.cs +++ b/src/ReactiveUI/Interfaces/IObservedChange.cs @@ -16,17 +16,17 @@ namespace ReactiveUI public interface IObservedChange { /// - /// The object that has raised the change. + /// Gets the object that has raised the change. /// TSender Sender { get; } /// - /// The expression of the member that has changed on Sender. + /// Gets the expression of the member that has changed on Sender. /// Expression Expression { get; } /// - /// The value of the property that has changed. IMPORTANT NOTE: This + /// Gets the value of the property that has changed. IMPORTANT NOTE: This /// property is often not set for performance reasons, unless you have /// explicitly requested an Observable for a property via a method such /// as ObservableForProperty. To retrieve the value for the property, diff --git a/src/ReactiveUI/Interfaces/IPlatformOperations.cs b/src/ReactiveUI/Interfaces/IPlatformOperations.cs index 5b417b2c..74c3ac84 100644 --- a/src/ReactiveUI/Interfaces/IPlatformOperations.cs +++ b/src/ReactiveUI/Interfaces/IPlatformOperations.cs @@ -13,7 +13,7 @@ namespace ReactiveUI /// Gets a descriptor that describes (if applicable) the orientation /// of the screen. /// - /// The orientation of the screen if supported. + /// The device orientation descriptor. string GetOrientation(); } } diff --git a/src/ReactiveUI/Interfaces/IReactiveNotifyPropertyChanged.cs b/src/ReactiveUI/Interfaces/IReactiveNotifyPropertyChanged.cs index 07961a92..aa6097a3 100644 --- a/src/ReactiveUI/Interfaces/IReactiveNotifyPropertyChanged.cs +++ b/src/ReactiveUI/Interfaces/IReactiveNotifyPropertyChanged.cs @@ -14,14 +14,14 @@ namespace ReactiveUI public interface IReactiveNotifyPropertyChanged { /// - /// Represents an Observable that fires *before* a property is about to + /// Gets an observable that fires *before* a property is about to /// be changed. Note that this should not fire duplicate change notifications if a /// property is set to the same value multiple times. /// IObservable> Changing { get; } /// - /// Represents an Observable that fires *after* a property has changed. + /// Gets an Observable that fires *after* a property has changed. /// Note that this should not fire duplicate change notifications if a /// property is set to the same value multiple times. /// diff --git a/src/ReactiveUI/Interfaces/IReactivePropertyChangedEventArgs.cs b/src/ReactiveUI/Interfaces/IReactivePropertyChangedEventArgs.cs index e568e64b..ae6e6d7f 100644 --- a/src/ReactiveUI/Interfaces/IReactivePropertyChangedEventArgs.cs +++ b/src/ReactiveUI/Interfaces/IReactivePropertyChangedEventArgs.cs @@ -16,12 +16,12 @@ namespace ReactiveUI public interface IReactivePropertyChangedEventArgs { /// - /// The name of the property that has changed on Sender. + /// Gets the name of the property that has changed on Sender. /// string PropertyName { get; } /// - /// The object that has raised the change. + /// Gets the object that has raised the change. /// TSender Sender { get; } } diff --git a/src/ReactiveUI/Interfaces/IRoutableViewModel.cs b/src/ReactiveUI/Interfaces/IRoutableViewModel.cs index 22fea4e8..c20cc46b 100644 --- a/src/ReactiveUI/Interfaces/IRoutableViewModel.cs +++ b/src/ReactiveUI/Interfaces/IRoutableViewModel.cs @@ -10,12 +10,12 @@ namespace ReactiveUI public interface IRoutableViewModel : IReactiveObject { /// - /// A string token representing the current ViewModel, such as 'login' or 'user'. + /// Gets a string token representing the current ViewModel, such as 'login' or 'user'. /// string UrlPathSegment { get; } /// - /// The IScreen that this ViewModel is currently being shown in. This + /// Gets the IScreen that this ViewModel is currently being shown in. This /// is usually passed into the ViewModel in the Constructor and saved /// as a ReadOnly Property. /// diff --git a/src/ReactiveUI/Interfaces/IScreen.cs b/src/ReactiveUI/Interfaces/IScreen.cs index 5e242235..b63c7aa0 100644 --- a/src/ReactiveUI/Interfaces/IScreen.cs +++ b/src/ReactiveUI/Interfaces/IScreen.cs @@ -11,7 +11,7 @@ namespace ReactiveUI public interface IScreen { /// - /// The Router associated with this Screen. + /// Gets the Router associated with this Screen. /// RoutingState Router { get; } } diff --git a/src/ReactiveUI/Interfaces/ISuspensionHost.cs b/src/ReactiveUI/Interfaces/ISuspensionHost.cs index 93ebc108..add34ae6 100644 --- a/src/ReactiveUI/Interfaces/ISuspensionHost.cs +++ b/src/ReactiveUI/Interfaces/ISuspensionHost.cs @@ -27,45 +27,45 @@ namespace ReactiveUI public interface ISuspensionHost : IReactiveObject { /// - /// Signals when the application is launching new. This can happen when + /// Gets or sets the observable which signals when the application is launching new. This can happen when /// an app has recently crashed, as well as the first time the app has /// been launched. Apps should create their state from scratch. /// IObservable IsLaunchingNew { get; set; } /// - /// Signals when the application is resuming from suspended state (i.e. + /// Gets or sets the observable which signals when the application is resuming from suspended state (i.e. /// it was previously running but its process was destroyed). /// IObservable IsResuming { get; set; } /// - /// Signals when the application is activated. Note that this may mean + /// Gets or sets the observable which signals when the application is activated. Note that this may mean /// that your process was not actively running before this signal. /// IObservable IsUnpausing { get; set; } /// - /// Signals when the application should persist its state to disk. + /// Gets or sets the observable which signals when the application should persist its state to disk. /// /// Returns an IDisposable that should be disposed once the /// application finishes persisting its state. IObservable ShouldPersistState { get; set; } /// - /// Signals that the saved application state should be deleted, this + /// Gets or sets the observable which signals that the saved application state should be deleted, this /// usually is called after an app has crashed. /// IObservable ShouldInvalidateState { get; set; } /// - /// A method that can be used to create a new application state - usually + /// Gets or sets a function that can be used to create a new application state - usually /// this method just calls 'new' on an object. /// Func CreateNewAppState { get; set; } /// - /// The current application state - get a typed version of this via + /// Gets or sets the current application state - get a typed version of this via /// . /// The "application state" is a notion entirely defined /// via the client application - the framework places no restrictions on diff --git a/src/ReactiveUI/Interfaces/ReactivePropertyChangedEventArgs.cs b/src/ReactiveUI/Interfaces/ReactivePropertyChangedEventArgs.cs index ec400383..d7f1dee0 100644 --- a/src/ReactiveUI/Interfaces/ReactivePropertyChangedEventArgs.cs +++ b/src/ReactiveUI/Interfaces/ReactivePropertyChangedEventArgs.cs @@ -28,6 +28,6 @@ namespace ReactiveUI /// Gets the sender which triggered the property changed event. /// /// - public TSender Sender { get; private set; } + public TSender Sender { get; } } } diff --git a/src/ReactiveUI/Interfaces/ReactivePropertyChangingEventArgs.cs b/src/ReactiveUI/Interfaces/ReactivePropertyChangingEventArgs.cs index 45cfc528..9ee72677 100644 --- a/src/ReactiveUI/Interfaces/ReactivePropertyChangingEventArgs.cs +++ b/src/ReactiveUI/Interfaces/ReactivePropertyChangingEventArgs.cs @@ -25,6 +25,6 @@ namespace ReactiveUI /// Gets the sender which triggered the Reactive property changed event. /// /// - public TSender Sender { get; private set; } + public TSender Sender { get; } } } diff --git a/src/ReactiveUI/Legacy/IReactiveList.cs b/src/ReactiveUI/Legacy/IReactiveList.cs index 255043bf..5d242d68 100644 --- a/src/ReactiveUI/Legacy/IReactiveList.cs +++ b/src/ReactiveUI/Legacy/IReactiveList.cs @@ -5,8 +5,6 @@ using System; using System.Collections.Generic; -#pragma warning disable SA1600 // Elements should be documented -- not used for legacy - namespace ReactiveUI.Legacy { /// @@ -22,20 +20,55 @@ namespace ReactiveUI.Legacy [Obsolete("ReactiveList is no longer supported. We suggest replacing it with DynamicData https://github.com/rolandpheasant/dynamicdata")] public interface IReactiveList : IReactiveCollection, IList { + /// + /// Gets a value indicating whether the collection is empty. + /// bool IsEmpty { get; } + /// + /// Adds a range of elements to the collection. + /// + /// A collection of values to add. void AddRange(IEnumerable collection); + /// + /// Inserts a range of elements to the collection at the specified index. + /// + /// The index to start adding the items to. + /// A collection of values to add. void InsertRange(int index, IEnumerable collection); + /// + /// Remove all the items contained within the specified collection. + /// + /// The items to remove. void RemoveAll(IEnumerable items); + /// + /// Removes items contained at the starting index going to count. + /// + /// The index to start removing items from. + /// The number of items to remove. void RemoveRange(int index, int count); + /// + /// Sort the container using the specified comparer. + /// + /// The comparer to use to sort the list. If none is specified the default comparer will be used. void Sort(IComparer comparer = null); + /// + /// Sort the container using the specified comparison method. + /// + /// The comparison type to use to sort the list. void Sort(Comparison comparison); + /// + /// Sort the items based at the specified index for the number of items specified by the count. + /// + /// The index to start sorting at. + /// The count to sort. + /// The comparer to use to sort the list. void Sort(int index, int count, IComparer comparer); } } diff --git a/src/ReactiveUI/Legacy/IReactiveNotifyCollectionChanged.cs b/src/ReactiveUI/Legacy/IReactiveNotifyCollectionChanged.cs index d9a704a2..78c30bb0 100644 --- a/src/ReactiveUI/Legacy/IReactiveNotifyCollectionChanged.cs +++ b/src/ReactiveUI/Legacy/IReactiveNotifyCollectionChanged.cs @@ -19,69 +19,74 @@ namespace ReactiveUI.Legacy public interface IReactiveNotifyCollectionChanged { /// - /// Fires when items are added to the collection, once per item added. + /// Gets an observable that signals when items are added to the collection, once per item added. /// Functions that add multiple items such AddRange should fire this /// multiple times. The object provided is the item that was added. /// IObservable ItemsAdded { get; } /// - /// Fires before an item is going to be added to the collection. + /// Gets an observable that signals before an item is going to be added to the collection. /// IObservable BeforeItemsAdded { get; } /// - /// Fires once an item has been removed from a collection, providing the + /// Gets an observable that signals once an item has been removed from a collection, providing the /// item that was removed. /// IObservable ItemsRemoved { get; } /// - /// Fires before an item will be removed from a collection, providing + /// Gets an observable that signals before an item will be removed from a collection, providing /// the item that will be removed. /// IObservable BeforeItemsRemoved { get; } /// - /// Fires before an items moves from one position in the collection to + /// Gets an observable that signals before an items moves from one position in the collection to /// another, providing the item(s) to be moved as well as source and destination /// indices. /// IObservable> BeforeItemsMoved { get; } /// - /// Fires once one or more items moves from one position in the collection to + /// Gets an observable that signals once one or more items moves from one position in the collection to /// another, providing the item(s) that was moved as well as source and destination /// indices. /// IObservable> ItemsMoved { get; } /// + /// Gets an observable that signals when the collection is changing. /// This Observable is equivalent to the NotifyCollectionChanged event, /// but fires before the collection is changed. /// IObservable Changing { get; } /// + /// Gets an observable that signals when the collection has changed. /// This Observable is equivalent to the NotifyCollectionChanged event, /// and fires after the collection is changed. /// IObservable Changed { get; } /// - /// Fires when the collection count changes, regardless of reason. + /// Gets an observable that signals when the collection count changes, regardless of reason. /// IObservable CountChanging { get; } /// - /// Fires when the collection count changes, regardless of reason. + /// Gets an observable that signals when the collection count changes, regardless of reason. /// IObservable CountChanged { get; } + /// + /// Gets an observable that signals when the collection has become empty or not. + /// IObservable IsEmptyChanged { get; } /// - /// This Observable is fired when a ShouldReset fires on the collection. This + /// Gets an observable that signals when a ShouldReset fires on the collection. This /// means that you should forget your previous knowledge of the state /// of the collection and reread it. /// @@ -90,6 +95,10 @@ namespace ReactiveUI.Legacy /// IObservable ShouldReset { get; } + /// + /// Stops change notifications, and returns a disposable which when disposed will trigger a reset event. + /// + /// The disposable to use to turn back on notifications. IDisposable SuppressChangeNotifications(); } } diff --git a/src/ReactiveUI/Legacy/IReactiveNotifyCollectionItemChanged.cs b/src/ReactiveUI/Legacy/IReactiveNotifyCollectionItemChanged.cs index 878d4cad..1fde1419 100644 --- a/src/ReactiveUI/Legacy/IReactiveNotifyCollectionItemChanged.cs +++ b/src/ReactiveUI/Legacy/IReactiveNotifyCollectionItemChanged.cs @@ -15,24 +15,21 @@ namespace ReactiveUI.Legacy public interface IReactiveNotifyCollectionItemChanged { /// - /// Provides Item Changing notifications for any item in collection that + /// Gets an observable that signals when item changing notifications have occurred for any item in collection that /// implements IReactiveNotifyPropertyChanged. This is only enabled when /// ChangeTrackingEnabled is set to True. /// IObservable> ItemChanging { get; } /// - /// Provides Item Changed notifications for any item in collection that + /// Gets an observable that signals when item change notifications have occurred Item Changed notifications for any item in collection that /// implements IReactiveNotifyPropertyChanged. This is only enabled when /// ChangeTrackingEnabled is set to True. /// IObservable> ItemChanged { get; } /// - /// Enables the ItemChanging and ItemChanged properties; when this is - /// enabled, whenever a property on any object implementing - /// IReactiveNotifyPropertyChanged changes, the change will be - /// rebroadcast through ItemChanging/ItemChanged. + /// Gets or sets a value indicating whether to track if contained items INotifyPropertyChanged events have been triggered. /// bool ChangeTrackingEnabled { get; set; } } diff --git a/src/ReactiveUI/Legacy/IReadOnlyReactiveList.cs b/src/ReactiveUI/Legacy/IReadOnlyReactiveList.cs index a9481e1c..956fab47 100644 --- a/src/ReactiveUI/Legacy/IReadOnlyReactiveList.cs +++ b/src/ReactiveUI/Legacy/IReadOnlyReactiveList.cs @@ -5,8 +5,6 @@ using System; using System.Collections.Generic; -#pragma warning disable SA1600 // Elements should be documented -- not used for legacy - namespace ReactiveUI.Legacy { /// @@ -22,6 +20,9 @@ namespace ReactiveUI.Legacy [Obsolete("ReactiveList is no longer supported. We suggest replacing it with DynamicData https://github.com/rolandpheasant/dynamicdata")] public interface IReadOnlyReactiveList : IReadOnlyReactiveCollection, IReadOnlyList { + /// + /// Gets a value indicating whether the list is empty. + /// bool IsEmpty { get; } } } diff --git a/src/ReactiveUI/Legacy/MoveInfo.cs b/src/ReactiveUI/Legacy/MoveInfo.cs index 189d4ed1..a20cff1b 100644 --- a/src/ReactiveUI/Legacy/MoveInfo.cs +++ b/src/ReactiveUI/Legacy/MoveInfo.cs @@ -6,6 +6,10 @@ using System.Collections.Generic; namespace ReactiveUI.Legacy { + /// + /// Information about a move between locations within a Reactive collection. + /// + /// The type of item contained in the move. internal class MoveInfo : IMoveInfo { public MoveInfo(IEnumerable movedItems, int from, int to) diff --git a/src/ReactiveUI/Legacy/ReactiveDerivedCollection.cs b/src/ReactiveUI/Legacy/ReactiveDerivedCollection.cs index 45e4f5c8..211cd09e 100644 --- a/src/ReactiveUI/Legacy/ReactiveDerivedCollection.cs +++ b/src/ReactiveUI/Legacy/ReactiveDerivedCollection.cs @@ -26,6 +26,7 @@ using Splat; #pragma warning disable SA1100 // Do not use prefix -- not used for legacy #pragma warning disable SA1407 // Expression should declare precedence -- not used for legacy #pragma warning disable SA1402 // File many contain only single type -- not used for legacy +#pragma warning disable SA1405 // Asset should provide message -- not used for legacy namespace ReactiveUI.Legacy { diff --git a/src/ReactiveUI/Legacy/ReactiveList.cs b/src/ReactiveUI/Legacy/ReactiveList.cs index 8f324646..ddb03822 100644 --- a/src/ReactiveUI/Legacy/ReactiveList.cs +++ b/src/ReactiveUI/Legacy/ReactiveList.cs @@ -53,7 +53,7 @@ namespace ReactiveUI.Legacy CollectionChanged?.Invoke(this, ReplaceIfUnsupported(args)); } - private NotifyCollectionChangedEventArgs ReplaceIfUnsupported(NotifyCollectionChangedEventArgs args) + private static NotifyCollectionChangedEventArgs ReplaceIfUnsupported(NotifyCollectionChangedEventArgs args) { // see System.Windows.Data.ListCollectionView.ValidateCollectionChangedEventArgs switch (args.Action) diff --git a/src/ReactiveUI/Mixins/DependencyResolverMixins.cs b/src/ReactiveUI/Mixins/DependencyResolverMixins.cs index ab5c2316..ba7c0924 100644 --- a/src/ReactiveUI/Mixins/DependencyResolverMixins.cs +++ b/src/ReactiveUI/Mixins/DependencyResolverMixins.cs @@ -3,6 +3,8 @@ // See the LICENSE file in the project root for more information. using System; +using System.Diagnostics.CodeAnalysis; +using System.Globalization; using System.Linq; using System.Linq.Expressions; using System.Reflection; @@ -21,6 +23,7 @@ namespace ReactiveUI /// Locator.Current. /// /// The resolver to initialize. + [SuppressMessage("Globalization", "CA1307: operator could change based on locale settings", Justification = "Replace() does not have third parameter on all platforms")] public static void InitializeReactiveUI(this IMutableDependencyResolver resolver) { var extraNs = new[] @@ -36,10 +39,9 @@ namespace ReactiveUI var fdr = typeof(DependencyResolverMixins); - var assmName = new AssemblyName( - fdr.AssemblyQualifiedName.Replace(fdr.FullName + ", ", string.Empty)); + var assemblyName = new AssemblyName(fdr.AssemblyQualifiedName.Replace(fdr.FullName + ", ", string.Empty)); - extraNs.ForEach(ns => ProcessRegistrationForNamespace(ns, assmName, resolver)); + extraNs.ForEach(ns => ProcessRegistrationForNamespace(ns, assemblyName, resolver)); } /// @@ -84,6 +86,7 @@ namespace ReactiveUI } } + [SuppressMessage("Redundancy", "CA1801: Redundant parameter", Justification = "Used on some platforms")] private static Func TypeFactory(TypeInfo typeInfo) { #if PORTABLE @@ -94,6 +97,7 @@ namespace ReactiveUI #endif } + [SuppressMessage("Globalization", "CA1307: operator could change based on locale settings", Justification = "Replace() does not have third parameter on all platforms")] private static void ProcessRegistrationForNamespace(string ns, AssemblyName assemblyName, IMutableDependencyResolver resolver) { var targetType = ns + ".Registrations"; @@ -102,9 +106,9 @@ namespace ReactiveUI var registerTypeClass = Reflection.ReallyFindType(fullName, false); if (registerTypeClass != null) { - var registerer = (IWantsToRegisterStuff)Activator.CreateInstance(registerTypeClass); - registerer.Register((f, t) => resolver.RegisterConstant(f(), t)); + var registerer = (IWantsToRegisterStuff)Activator.CreateInstance(registerTypeClass); + registerer.Register((f, t) => resolver.RegisterConstant(f(), t)); + } } } } -} diff --git a/src/ReactiveUI/ObservableForProperty/ObservableAsPropertyHelper.cs b/src/ReactiveUI/ObservableForProperty/ObservableAsPropertyHelper.cs index 2bba27c0..0f36bc5a 100644 --- a/src/ReactiveUI/ObservableForProperty/ObservableAsPropertyHelper.cs +++ b/src/ReactiveUI/ObservableForProperty/ObservableAsPropertyHelper.cs @@ -126,7 +126,7 @@ namespace ReactiveUI } /// - /// The last provided value from the Observable. + /// Gets the last provided value from the Observable. /// public T Value { @@ -142,7 +142,7 @@ namespace ReactiveUI } /// - /// Gets a boolean value indicating whether the ObservableAsPropertyHelper + /// Gets a value indicating whether the ObservableAsPropertyHelper /// has subscribed to the source Observable. /// Useful for scenarios where you use deferred subscription and want to know if /// the ObservableAsPropertyHelper Value has been accessed yet. @@ -150,7 +150,7 @@ namespace ReactiveUI public bool IsSubscribed => _activated > 0; /// - /// Fires whenever an exception would normally terminate ReactiveUI + /// Gets an observable which signals whenever an exception would normally terminate ReactiveUI /// internal state. /// public IObservable ThrownExceptions { get; } diff --git a/src/ReactiveUI/Platforms/android/AndroidCommandBinders.cs b/src/ReactiveUI/Platforms/android/AndroidCommandBinders.cs index daa5dc21..61ffd65d 100644 --- a/src/ReactiveUI/Platforms/android/AndroidCommandBinders.cs +++ b/src/ReactiveUI/Platforms/android/AndroidCommandBinders.cs @@ -15,11 +15,6 @@ namespace ReactiveUI /// public class AndroidCommandBinders : FlexibleCommandBinder { - /// - /// The static instance of . - /// - public static Lazy Instance = new Lazy(); - /// /// Initializes a new instance of the class. /// @@ -28,5 +23,10 @@ namespace ReactiveUI Type view = typeof(View); Register(view, 9, (cmd, t, cp) => ForEvent(cmd, t, cp, "Click", view.GetRuntimeProperty("Enabled"))); } + + /// + /// Gets the static instance of . + /// + public static Lazy Instance { get; } = new Lazy(); } } diff --git a/src/ReactiveUI/Platforms/android/AndroidObservableForWidgets.cs b/src/ReactiveUI/Platforms/android/AndroidObservableForWidgets.cs index 2a531ebe..6db861a8 100644 --- a/src/ReactiveUI/Platforms/android/AndroidObservableForWidgets.cs +++ b/src/ReactiveUI/Platforms/android/AndroidObservableForWidgets.cs @@ -59,15 +59,6 @@ namespace ReactiveUI return dispatchTable[tableItem](sender, expression); } - private class DispatchTuple - { - public Type Type { get; set; } - - public string Property { get; set; } - - public Func>> Func { get; set; } - } - private static DispatchTuple CreateFromAdapterView() { // AdapterView is more complicated because there are two events - one for select and one for deselect @@ -136,5 +127,14 @@ namespace ReactiveUI } }; } + + private class DispatchTuple + { + public Type Type { get; set; } + + public string Property { get; set; } + + public Func>> Func { get; set; } + } } } diff --git a/src/ReactiveUI/Platforms/android/AutoSuspendHelper.cs b/src/ReactiveUI/Platforms/android/AutoSuspendHelper.cs index fb491820..2893707c 100644 --- a/src/ReactiveUI/Platforms/android/AutoSuspendHelper.cs +++ b/src/ReactiveUI/Platforms/android/AutoSuspendHelper.cs @@ -19,28 +19,17 @@ namespace ReactiveUI /// /// Helps manage android application lifecycle events. /// - public class AutoSuspendHelper : IEnableLogger + public class AutoSuspendHelper : IEnableLogger, IDisposable { private readonly Subject _onCreate = new Subject(); private readonly Subject _onRestart = new Subject(); private readonly Subject _onPause = new Subject(); private readonly Subject _onSaveInstanceState = new Subject(); - /// - /// The untimely demise of an application. - /// - public static readonly Subject UntimelyDemise = new Subject(); + private bool _disposedValue; // To detect redundant calls /// - /// Gets or sets the latest bundle. - /// - /// - /// The latest bundle. - /// - public static Bundle LatestBundle { get; set; } - - /// - /// Initializes the class. + /// Initializes static members of the class. /// static AutoSuspendHelper() { @@ -62,11 +51,51 @@ namespace ReactiveUI RxApp.SuspensionHost.IsUnpausing = _onRestart; RxApp.SuspensionHost.ShouldPersistState = Observable.Merge( - _onPause.Select(_ => Disposable.Empty), _onSaveInstanceState.Select(_ => Disposable.Empty)); + _onPause.Select(_ => Disposable.Empty), _onSaveInstanceState.Select(_ => Disposable.Empty)); RxApp.SuspensionHost.ShouldInvalidateState = UntimelyDemise; } + /// + /// Gets a subject to indicate whether the application has untimely dismised. + /// + public static Subject UntimelyDemise { get; } = new Subject(); + + /// + /// Gets or sets the latest bundle. + /// + public static Bundle LatestBundle { get; set; } + + /// + public void Dispose() + { + // Do not change this code. Put cleanup code in Dispose(bool disposing) above. + Dispose(true); + GC.SuppressFinalize(this); + } + + /// + /// Disposes of the items inside the class. + /// + /// If we are disposing of managed objects or not. + protected virtual void Dispose(bool disposing) + { + if (_disposedValue) + { + return; + } + + if (disposing) + { + _onCreate?.Dispose(); + _onPause?.Dispose(); + _onRestart?.Dispose(); + _onSaveInstanceState?.Dispose(); + } + + _disposedValue = true; + } + private class ObservableLifecycle : Java.Lang.Object, Application.IActivityLifecycleCallbacks { private readonly AutoSuspendHelper _this; diff --git a/src/ReactiveUI/Platforms/android/ContextExtensions.cs b/src/ReactiveUI/Platforms/android/ContextExtensions.cs index 95c00b98..e1ebf0cd 100644 --- a/src/ReactiveUI/Platforms/android/ContextExtensions.cs +++ b/src/ReactiveUI/Platforms/android/ContextExtensions.cs @@ -62,24 +62,20 @@ namespace ReactiveUI /// A private implementation of IServiceConnection and IDisposable. /// /// The binder type. - private class ServiceConnection - : Java.Lang.Object, - IServiceConnection - where TBinder - : class, - IBinder + private class ServiceConnection : Java.Lang.Object, IServiceConnection + where TBinder : class, IBinder { private readonly Context _context; private readonly IObserver _observer; + private bool _disposed; + public ServiceConnection(Context context, IObserver observer) { _context = context; _observer = observer; } - #region IServiceConnection implemention - void IServiceConnection.OnServiceConnected(ComponentName name, IBinder binder) { _observer.OnNext((TBinder)binder); @@ -91,12 +87,6 @@ namespace ReactiveUI _observer.OnNext(null); } - #endregion - - #region Dispose implementation - - private bool _disposed; - protected override void Dispose(bool disposing) { if (!_disposed) @@ -111,8 +101,6 @@ namespace ReactiveUI base.Dispose(disposing); } - - #endregion } } } diff --git a/src/ReactiveUI/Platforms/android/ControlFetcherMixin.cs b/src/ReactiveUI/Platforms/android/ControlFetcherMixin.cs index b8304aff..1ccf0c78 100644 --- a/src/ReactiveUI/Platforms/android/ControlFetcherMixin.cs +++ b/src/ReactiveUI/Platforms/android/ControlFetcherMixin.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; @@ -28,6 +29,7 @@ namespace ReactiveUI private static readonly MethodInfo getControlActivity; private static readonly MethodInfo getControlView; + [SuppressMessage("Design", "CA1065: Not not throw exceptions in static constructor", Justification = "TODO: Future fix")] static ControlFetcherMixin() { // NB: This is some hacky shit, but on Xamarin.Android at the moment, @@ -47,14 +49,15 @@ namespace ReactiveUI .Where(x => x.FieldType == typeof(int)) .GroupBy(k => k.Name.ToLowerInvariant()) .Where(g => g.Count() > 1) - .Select(g => "{ " + string.Join(" = ", g.Select(v => v.Name)) + " }"); + .Select(g => "{ " + string.Join(" = ", g.Select(v => v.Name)) + " }") + .ToList(); if (duplicates.Any()) { throw new InvalidOperationException("You're using multiple resource ID's with the same name but with different casings which isn't allowed for WireUpControls: " + string.Join(", ", duplicates), argumentException); } - throw argumentException; + throw; } var type = typeof(ControlFetcherMixin); @@ -63,7 +66,7 @@ namespace ReactiveUI } /// - /// Gets the control from an activiy. + /// Gets the control from an activity. /// /// The control type. /// The activity. @@ -73,7 +76,7 @@ namespace ReactiveUI where T : View => (T)GetCachedControl(propertyName, @this, () => @this.FindViewById(controlIds[propertyName.ToLowerInvariant()]).JavaCast()); /// - /// Gets the control from an activiy. + /// Gets the control from an activity. /// /// The control type. /// The view. @@ -83,7 +86,7 @@ namespace ReactiveUI where T : View => (T)GetCachedControl(propertyName, @this, () => @this.FindViewById(controlIds[propertyName.ToLowerInvariant()]).JavaCast()); /// - /// Gets the control from an activiy. + /// Gets the control from an activity. /// /// The control type. /// The fragment. @@ -212,18 +215,17 @@ namespace ReactiveUI private static View GetCachedControl(string propertyName, object rootView, Func fetchControlFromView) { - var ret = default(View); var ourViewCache = viewCache.GetOrCreateValue(rootView); - if (ourViewCache.TryGetValue(propertyName, out ret)) + if (ourViewCache.TryGetValue(propertyName, out View view)) { - return ret; + return view; } - ret = fetchControlFromView(); + view = fetchControlFromView(); - ourViewCache.Add(propertyName, ret); - return ret; + ourViewCache.Add(propertyName, view); + return view; } private static string GetResourceName(this PropertyInfo member) @@ -238,8 +240,7 @@ namespace ReactiveUI switch (resolveStrategy) { - default: - case ResolveStrategy.Implicit: + default: // Implicit matches the Default. return members.Where(m => m.PropertyType.IsSubclassOf(typeof(View)) || m.GetCustomAttribute(true) != null); @@ -252,41 +253,4 @@ namespace ReactiveUI } } } - - /// - /// Attribute that marks a resource for wiring. - /// - public class WireUpResourceAttribute : Attribute - { - /// - /// Gets the resource name override. - /// - /// - /// The resource name override. - /// - public string ResourceNameOverride { get; } - - /// - /// Initializes a new instance of the class. - /// - public WireUpResourceAttribute() - { - } - - /// - /// Initializes a new instance of the class. - /// - /// Name of the resource. - public WireUpResourceAttribute(string resourceName) - { - ResourceNameOverride = resourceName; - } - } - - /// - /// Attribute that marks a resource to be ignored. - /// - public class IgnoreResourceAttribute : Attribute - { - } } diff --git a/src/ReactiveUI/Platforms/android/FlexibleCommandBinder.cs b/src/ReactiveUI/Platforms/android/FlexibleCommandBinder.cs index ed7812a8..7b3af877 100644 --- a/src/ReactiveUI/Platforms/android/FlexibleCommandBinder.cs +++ b/src/ReactiveUI/Platforms/android/FlexibleCommandBinder.cs @@ -17,6 +17,11 @@ namespace ReactiveUI /// public abstract class FlexibleCommandBinder : ICreatesCommandBinding { + /// + /// Configuration map. + /// + private readonly Dictionary _config = new Dictionary(); + /// public int GetAffinityForObject(Type type, bool hasEventTarget) { @@ -68,29 +73,6 @@ namespace ReactiveUI throw new NotImplementedException(); } - private class CommandBindingInfo - { - public int Affinity { get; set; } - - public Func, IDisposable> CreateBinding { get; set; } - } - - /// - /// Configuration map. - /// - private readonly Dictionary _config = new Dictionary(); - - /// - /// Registers an observable factory for the specified type and property. - /// - /// Type. - /// The affinity for the type. - /// Creates the binding. - protected void Register(Type type, int affinity, Func, IDisposable> createBinding) - { - _config[type] = new CommandBindingInfo { Affinity = affinity, CreateBinding = createBinding }; - } - /// /// Creates a commands binding from event and a property. /// @@ -133,5 +115,23 @@ namespace ReactiveUI return compDisp; } + + /// + /// Registers an observable factory for the specified type and property. + /// + /// Type. + /// The affinity for the type. + /// Creates the binding. + protected void Register(Type type, int affinity, Func, IDisposable> createBinding) + { + _config[type] = new CommandBindingInfo { Affinity = affinity, CreateBinding = createBinding }; + } + + private class CommandBindingInfo + { + public int Affinity { get; set; } + + public Func, IDisposable> CreateBinding { get; set; } + } } } diff --git a/src/ReactiveUI/Platforms/android/AndroidUIScheduler.cs b/src/ReactiveUI/Platforms/android/HandlerScheduler.cs similarity index 86% rename from src/ReactiveUI/Platforms/android/AndroidUIScheduler.cs rename to src/ReactiveUI/Platforms/android/HandlerScheduler.cs index 77136518..19679e3b 100644 --- a/src/ReactiveUI/Platforms/android/AndroidUIScheduler.cs +++ b/src/ReactiveUI/Platforms/android/HandlerScheduler.cs @@ -1,4 +1,4 @@ -// Licensed to the .NET Foundation under one or more agreements. +// 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. @@ -22,12 +22,8 @@ namespace ReactiveUI /// public class HandlerScheduler : IScheduler, IEnableLogger { - /// - /// A common instance to avoid allocations to the MainThread for the HandlerScheduler. - /// - public static IScheduler MainThreadScheduler = new HandlerScheduler(new Handler(Looper.MainLooper), Looper.MainLooper.Thread.Id); - private Handler _handler; - private long _looperId; + private readonly Handler _handler; + private readonly long _looperId; /// /// Initializes a new instance of the class. @@ -40,6 +36,14 @@ namespace ReactiveUI _looperId = threadIdAssociatedWithHandler ?? -1; } + /// + /// Gets a common instance to avoid allocations to the MainThread for the HandlerScheduler. + /// + public static IScheduler MainThreadScheduler { get; } = new HandlerScheduler(new Handler(Looper.MainLooper), Looper.MainLooper.Thread.Id); + + /// + public DateTimeOffset Now => DateTimeOffset.Now; + /// public IDisposable Schedule(TState state, Func action) { @@ -98,12 +102,6 @@ namespace ReactiveUI return Schedule(state, dueTime - Now, action); } - - /// - public DateTimeOffset Now - { - get { return DateTimeOffset.Now; } - } } } diff --git a/src/ReactiveUI/Platforms/android/ILayoutViewHost.cs b/src/ReactiveUI/Platforms/android/ILayoutViewHost.cs new file mode 100644 index 00000000..47a10137 --- /dev/null +++ b/src/ReactiveUI/Platforms/android/ILayoutViewHost.cs @@ -0,0 +1,22 @@ +// 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 Android.Views; + +namespace ReactiveUI +{ + /// + /// Interface that defines a layout view host. + /// + public interface ILayoutViewHost + { + /// + /// Gets the view. + /// + /// + /// The view. + /// + View View { get; } + } +} diff --git a/src/ReactiveUI/Platforms/android/IgnoreResourceAttribute.cs b/src/ReactiveUI/Platforms/android/IgnoreResourceAttribute.cs new file mode 100644 index 00000000..34e351ae --- /dev/null +++ b/src/ReactiveUI/Platforms/android/IgnoreResourceAttribute.cs @@ -0,0 +1,12 @@ +using System; + +namespace ReactiveUI +{ + /// + /// Attribute that marks a resource to be ignored. + /// + [AttributeUsage(AttributeTargets.All)] + public class IgnoreResourceAttribute : Attribute + { + } +} diff --git a/src/ReactiveUI/Platforms/android/JavaHolder.cs b/src/ReactiveUI/Platforms/android/JavaHolder.cs new file mode 100644 index 00000000..1025e268 --- /dev/null +++ b/src/ReactiveUI/Platforms/android/JavaHolder.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text; + +using Object = Java.Lang.Object; + +namespace ReactiveUI +{ + internal class JavaHolder : Object + { + [SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1401: Field should be private", Justification = "Used for interop purposes")] + public readonly object Instance; + + public JavaHolder(object instance) + { + Instance = instance; + } + } +} diff --git a/src/ReactiveUI/Platforms/android/LayoutViewHost.cs b/src/ReactiveUI/Platforms/android/LayoutViewHost.cs index 9c60df0d..0fb86b63 100644 --- a/src/ReactiveUI/Platforms/android/LayoutViewHost.cs +++ b/src/ReactiveUI/Platforms/android/LayoutViewHost.cs @@ -3,82 +3,13 @@ // See the LICENSE file in the project root for more information. using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Diagnostics.Contracts; -using System.Linq; -using System.Reactive.Concurrency; -using System.Reactive.Disposables; -using System.Reactive.Subjects; -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.Serialization; -using System.Threading; -using Android.App; +using System.Diagnostics.CodeAnalysis; using Android.Content; using Android.Views; using Splat; namespace ReactiveUI { - /// - /// Interface that defines a layout view host. - /// - public interface ILayoutViewHost - { - /// - /// Gets the view. - /// - /// - /// The view. - /// - View View { get; } - } - - /// - /// Default methods for . - /// - public static class ViewMixins - { - internal const int ViewHostTag = -4222; - - /// - /// Gets the ViewHost associated with a given View by accessing the - /// Tag of the View. - /// - /// The layout view host type. - /// The view. - /// The view host. - public static T GetViewHost(this View @this) - where T : ILayoutViewHost - { - var tagData = @this.GetTag(ViewHostTag); - if (tagData != null) - { - return tagData.ToNetObject(); - } - - return default(T); - } - - /// - /// Gets the ViewHost associated with a given View by accessing the - /// Tag of the View. - /// - /// The view. - /// The view host. - public static ILayoutViewHost GetViewHost(this View @this) - { - var tagData = @this.GetTag(ViewHostTag); - if (tagData != null) - { - return tagData.ToNetObject(); - } - - return null; - } - } - /// /// A class that implements the Android ViewHolder pattern. Use it along /// with GetViewHost. @@ -87,28 +18,6 @@ namespace ReactiveUI { private View _view; - /// - public View View - { - get => _view; - - set - { - if (_view == value) - { - return; - } - - _view = value; - _view.SetTag(ViewMixins.ViewHostTag, this.ToJavaObject()); - } - } - - public static implicit operator View(LayoutViewHost @this) - { - return @this.View; - } - /// /// Initializes a new instance of the class. /// @@ -134,145 +43,29 @@ namespace ReactiveUI this.WireUpControls(); } } - } - - /// - /// A class that implements the Android ViewHolder pattern with a - /// ViewModel. Use it along with GetViewHost. - /// - /// The view model type. - public abstract class ReactiveViewHost : LayoutViewHost, IViewFor, IReactiveNotifyPropertyChanged>, IReactiveObject - where TViewModel : class, IReactiveObject - { - private TViewModel _viewModel; - - /// - /// Initializes a new instance of the class. - /// - /// The CTX. - /// The layout identifier. - /// The parent. - /// if set to true [attach to root]. - /// if set to true [perform automatic wireup]. - protected ReactiveViewHost(Context ctx, int layoutId, ViewGroup parent, bool attachToRoot = false, bool performAutoWireup = true) - : base(ctx, layoutId, parent, attachToRoot, performAutoWireup) - { - SetupRxObj(); - } - - /// - /// Initializes a new instance of the class. - /// - protected ReactiveViewHost() - { - SetupRxObj(); - } /// - public TViewModel ViewModel + public View View { - get { return _viewModel; } - set { this.RaiseAndSetIfChanged(ref _viewModel, value); } - } + get => _view; - /// - object IViewFor.ViewModel - { - get { return _viewModel; } - set { _viewModel = (TViewModel)value; } - } + set + { + if (_view == value) + { + return; + } - /// - public event PropertyChangingEventHandler PropertyChanging - { - add { PropertyChangingEventManager.AddHandler(this, value); } - remove { PropertyChangingEventManager.RemoveHandler(this, value); } - } - - /// - void IReactiveObject.RaisePropertyChanging(PropertyChangingEventArgs args) - { - PropertyChangingEventManager.DeliverEvent(this, args); - } - - /// - public event PropertyChangedEventHandler PropertyChanged - { - add { PropertyChangedEventManager.AddHandler(this, value); } - remove { PropertyChangedEventManager.RemoveHandler(this, value); } - } - - /// - void IReactiveObject.RaisePropertyChanged(PropertyChangedEventArgs args) - { - PropertyChangedEventManager.DeliverEvent(this, args); + _view = value; + _view.SetTag(ViewMixins.ViewHostTag, this.ToJavaObject()); + } } /// - /// Represents an Observable that fires *before* a property is about to - /// be changed. + /// Casts the LayoutViewHost to a View. /// - [IgnoreDataMember] - public IObservable>> Changing - { - get { return this.GetChangingObservable(); } - } - - /// - /// Represents an Observable that fires *after* a property has changed. - /// - [IgnoreDataMember] - public IObservable>> Changed - { - get { return this.GetChangedObservable(); } - } - - /// - /// All public properties. - /// - [IgnoreDataMember] - protected Lazy allPublicProperties; - - /// - /// Gets the thrown exceptions. - /// - [IgnoreDataMember] - public IObservable ThrownExceptions - { - get { return this.GetThrownExceptionsObservable(); } - } - - [OnDeserialized] - private void SetupRxObj(StreamingContext sc) - { - SetupRxObj(); - } - - private void SetupRxObj() - { - allPublicProperties = new Lazy(() => - GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance).ToArray()); - } - - /// - /// When this method is called, an object will not fire change - /// notifications (neither traditional nor Observable notifications) - /// until the return value is disposed. - /// - /// An object that, when disposed, reenables change - /// notifications. - public IDisposable SuppressChangeNotifications() - { - return IReactiveObjectExtensions.SuppressChangeNotifications(this); - } - - /// - /// Gets a value indicating if change notifications are enabled. - /// - /// A value indicating if change notifications are on or off. - public bool AreChangeNotificationsEnabled() - { - return IReactiveObjectExtensions.AreChangeNotificationsEnabled(this); - } + /// The LayoutViewHost to cast. + [SuppressMessage("Usage", "CA2225: Provide a method named ToView", Justification = "A property is already provided.")] + public static implicit operator View(LayoutViewHost @this) => @this.View; } } diff --git a/src/ReactiveUI/Platforms/android/ObjectExtension.cs b/src/ReactiveUI/Platforms/android/ObjectExtension.cs index abf6ca88..42844c09 100644 --- a/src/ReactiveUI/Platforms/android/ObjectExtension.cs +++ b/src/ReactiveUI/Platforms/android/ObjectExtension.cs @@ -10,16 +10,6 @@ using Object = Java.Lang.Object; namespace ReactiveUI { - internal class JavaHolder : Object - { - public readonly object Instance; - - public JavaHolder(object instance) - { - Instance = instance; - } - } - internal static class ObjectExtension { public static TObject ToNetObject(this Object value) @@ -44,9 +34,7 @@ namespace ReactiveUI return null; } - var holder = new JavaHolder(value); - - return (Object)holder; + return new JavaHolder(value); } } } diff --git a/src/ReactiveUI/Platforms/android/ReactiveActivity.cs b/src/ReactiveUI/Platforms/android/ReactiveActivity.cs index abcdd0da..feb1545b 100644 --- a/src/ReactiveUI/Platforms/android/ReactiveActivity.cs +++ b/src/ReactiveUI/Platforms/android/ReactiveActivity.cs @@ -3,29 +3,17 @@ // See the LICENSE file in the project root for more information. using System; -using System.Collections.Generic; using System.ComponentModel; -using System.Diagnostics.Contracts; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Reactive; -using System.Reactive.Concurrency; -using System.Reactive.Disposables; using System.Reactive.Linq; using System.Reactive.Subjects; using System.Reactive.Threading.Tasks; -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.Serialization; -using System.Text; -using System.Threading; using System.Threading.Tasks; using Android.App; using Android.Content; -using Android.OS; using Android.Runtime; -using Android.Views; -using Android.Widget; -using Splat; namespace ReactiveUI { @@ -34,11 +22,29 @@ namespace ReactiveUI /// (i.e. you can call RaiseAndSetIfChanged). /// /// The view model type. + [SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:FileMayOnlyContainASingleType", Justification = "Classes with the same class names within.")] public class ReactiveActivity : ReactiveActivity, IViewFor, ICanActivate where TViewModel : class { private TViewModel _viewModel; + /// + /// Initializes a new instance of the class. + /// + protected ReactiveActivity() + { + } + + /// + /// Initializes a new instance of the class. + /// + /// The handle. + /// The ownership. + protected ReactiveActivity(IntPtr handle, JniHandleOwnership ownership) + : base(handle, ownership) + { + } + /// public TViewModel ViewModel { @@ -52,16 +58,28 @@ namespace ReactiveUI get { return _viewModel; } set { _viewModel = (TViewModel)value; } } + } + + /// + /// This is an Activity that is both an Activity and has ReactiveObject powers + /// (i.e. you can call RaiseAndSetIfChanged). + /// + [SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:FileMayOnlyContainASingleType", Justification = "Classes with the same class names within.")] + public class ReactiveActivity : Activity, IReactiveObject, IReactiveNotifyPropertyChanged, IHandleObservableErrors + { + private readonly Subject _activated = new Subject(); + private readonly Subject _deactivated = new Subject(); + private readonly Subject> _activityResult = new Subject>(); /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// protected ReactiveActivity() { } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The handle. /// The ownership. @@ -69,16 +87,6 @@ namespace ReactiveUI : base(handle, ownership) { } - } - - /// - /// This is an Activity that is both an Activity and has ReactiveObject powers - /// (i.e. you can call RaiseAndSetIfChanged). - /// - public class ReactiveActivity : Activity, IReactiveObject, IReactiveNotifyPropertyChanged, IHandleObservableErrors - { - private readonly Subject _activated = new Subject(); - private readonly Subject _deactivated = new Subject(); /// public event PropertyChangingEventHandler PropertyChanging @@ -87,12 +95,6 @@ namespace ReactiveUI remove { PropertyChangingEventManager.RemoveHandler(this, value); } } - /// - void IReactiveObject.RaisePropertyChanging(PropertyChangingEventArgs args) - { - PropertyChangingEventManager.DeliverEvent(this, args); - } - /// public event PropertyChangedEventHandler PropertyChanged { @@ -100,45 +102,38 @@ namespace ReactiveUI remove { PropertyChangedEventManager.RemoveHandler(this, value); } } - /// - void IReactiveObject.RaisePropertyChanged(PropertyChangedEventArgs args) - { - PropertyChangedEventManager.DeliverEvent(this, args); - } - - /// - /// Represents an Observable that fires *before* a property is about to - /// be changed. - /// + /// public IObservable> Changing { get { return this.GetChangingObservable(); } } - /// - /// Represents an Observable that fires *after* a property has changed. - /// + /// public IObservable> Changed { get { return this.GetChangedObservable(); } } - /// - /// Initializes a new instance of the class. - /// - protected ReactiveActivity() - { - } + /// + public IObservable ThrownExceptions => this.GetThrownExceptionsObservable(); /// - /// Initializes a new instance of the class. + /// Gets a signal when the activity is activated. /// - /// The handle. - /// The ownership. - protected ReactiveActivity(IntPtr handle, JniHandleOwnership ownership) - : base(handle, ownership) - { - } + public IObservable Activated => _activated.AsObservable(); + + /// + /// Gets a signal when the activity is deactivated. + /// + public IObservable Deactivated => _deactivated.AsObservable(); + + /// + /// Gets the activity result. + /// + /// + /// The activity result. + /// + public IObservable> ActivityResult => _activityResult.AsObservable(); /// /// When this method is called, an object will not fire change @@ -150,65 +145,15 @@ namespace ReactiveUI public IDisposable SuppressChangeNotifications() => IReactiveObjectExtensions.SuppressChangeNotifications(this); /// - public IObservable ThrownExceptions + void IReactiveObject.RaisePropertyChanging(PropertyChangingEventArgs args) { - get => this.GetThrownExceptionsObservable(); - } - - /// - /// Gets a signal when the activity is activated. - /// - /// - /// The activated. - /// - public IObservable Activated - { - get => _activated.AsObservable(); - } - - /// - /// Gets a signal when the activity is deactivated. - /// - /// - /// The deactivated. - /// - public IObservable Deactivated - { - get { return _deactivated.AsObservable(); } + PropertyChangingEventManager.DeliverEvent(this, args); } /// - protected override void OnPause() + void IReactiveObject.RaisePropertyChanged(PropertyChangedEventArgs args) { - base.OnPause(); - _deactivated.OnNext(Unit.Default); - } - - /// - protected override void OnResume() - { - base.OnResume(); - _activated.OnNext(Unit.Default); - } - - private readonly Subject> _activityResult = new Subject>(); - - /// - /// Gets the activity result. - /// - /// - /// The activity result. - /// - public IObservable> ActivityResult - { - get { return _activityResult.AsObservable(); } - } - - /// - protected override void OnActivityResult(int requestCode, Result resultCode, Intent data) - { - base.OnActivityResult(requestCode, resultCode, data); - _activityResult.OnNext(Tuple.Create(requestCode, resultCode, data)); + PropertyChangedEventManager.DeliverEvent(this, args); } /// @@ -250,5 +195,26 @@ namespace ReactiveUI StartActivityForResult(type, requestCode); return ret; } + + /// + protected override void OnPause() + { + base.OnPause(); + _deactivated.OnNext(Unit.Default); + } + + /// + protected override void OnResume() + { + base.OnResume(); + _activated.OnNext(Unit.Default); + } + + /// + protected override void OnActivityResult(int requestCode, Result resultCode, Intent data) + { + base.OnActivityResult(requestCode, resultCode, data); + _activityResult.OnNext(Tuple.Create(requestCode, resultCode, data)); + } } } diff --git a/src/ReactiveUI/Platforms/android/ReactiveFragment.cs b/src/ReactiveUI/Platforms/android/ReactiveFragment.cs index c5e3d6fc..ea9eb4df 100644 --- a/src/ReactiveUI/Platforms/android/ReactiveFragment.cs +++ b/src/ReactiveUI/Platforms/android/ReactiveFragment.cs @@ -3,28 +3,13 @@ // See the LICENSE file in the project root for more information. using System; -using System.Collections.Generic; using System.ComponentModel; -using System.Diagnostics.Contracts; -using System.Linq; +using System.Diagnostics.CodeAnalysis; using System.Reactive; -using System.Reactive.Concurrency; -using System.Reactive.Disposables; using System.Reactive.Linq; using System.Reactive.Subjects; -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.Serialization; -using System.Text; -using System.Threading; using Android.App; -using Android.Content; -using Android.OS; using Android.Runtime; -using Android.Util; -using Android.Views; -using Android.Widget; -using Splat; namespace ReactiveUI { @@ -33,6 +18,7 @@ namespace ReactiveUI /// (i.e. you can call RaiseAndSetIfChanged). /// /// The view model type. + [SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:FileMayOnlyContainASingleType", Justification = "Classes with the same class names within.")] public class ReactiveFragment : ReactiveFragment, IViewFor, ICanActivate where TViewModel : class { @@ -74,25 +60,12 @@ namespace ReactiveUI /// This is a Fragment that is both an Activity and has ReactiveObject powers /// (i.e. you can call RaiseAndSetIfChanged). /// + [SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:FileMayOnlyContainASingleType", Justification = "Classes with the same class names within.")] public class ReactiveFragment : Fragment, IReactiveNotifyPropertyChanged, IReactiveObject, IHandleObservableErrors { private readonly Subject _activated = new Subject(); private readonly Subject _deactivated = new Subject(); - /// - public event PropertyChangingEventHandler PropertyChanging - { - add => PropertyChangingEventManager.AddHandler(this, value); - remove => PropertyChangingEventManager.RemoveHandler(this, value); - } - - /// - public event PropertyChangedEventHandler PropertyChanged - { - add => PropertyChangedEventManager.AddHandler(this, value); - remove => PropertyChangedEventManager.RemoveHandler(this, value); - } - /// /// Initializes a new instance of the class. /// @@ -110,15 +83,24 @@ namespace ReactiveUI { } - /// - /// Represents an Observable that fires *before* a property is about to - /// be changed. - /// + /// + public event PropertyChangingEventHandler PropertyChanging + { + add => PropertyChangingEventManager.AddHandler(this, value); + remove => PropertyChangingEventManager.RemoveHandler(this, value); + } + + /// + public event PropertyChangedEventHandler PropertyChanged + { + add => PropertyChangedEventManager.AddHandler(this, value); + remove => PropertyChangedEventManager.RemoveHandler(this, value); + } + + /// public IObservable> Changing => this.GetChangingObservable(); - /// - /// Represents an Observable that fires *after* a property has changed. - /// + /// public IObservable> Changed => this.GetChangedObservable(); /// diff --git a/src/ReactiveUI/Platforms/android/ReactiveListAdapter.cs b/src/ReactiveUI/Platforms/android/ReactiveListAdapter.cs index 8a6e305e..db211048 100644 --- a/src/ReactiveUI/Platforms/android/ReactiveListAdapter.cs +++ b/src/ReactiveUI/Platforms/android/ReactiveListAdapter.cs @@ -34,18 +34,6 @@ namespace ReactiveUI.Legacy _inner = _list.Changed.Subscribe(_ => NotifyDataSetChanged()); } - /// - public override TViewModel this[int index] - { - get { return _list[index]; } - } - - /// - public override long GetItemId(int position) - { - return _list[position].GetHashCode(); - } - /// public override bool HasStableIds { @@ -58,6 +46,18 @@ namespace ReactiveUI.Legacy get { return _list.Count; } } + /// + public override TViewModel this[int index] + { + get { return _list[index]; } + } + + /// + public override long GetItemId(int position) + { + return _list[position].GetHashCode(); + } + /// public override View GetView(int position, View convertView, ViewGroup parent) { diff --git a/src/ReactiveUI/Platforms/android/ReactivePreferenceActivity.cs b/src/ReactiveUI/Platforms/android/ReactivePreferenceActivity.cs index 675af449..9469f034 100644 --- a/src/ReactiveUI/Platforms/android/ReactivePreferenceActivity.cs +++ b/src/ReactiveUI/Platforms/android/ReactivePreferenceActivity.cs @@ -4,6 +4,7 @@ using System; using System.ComponentModel; +using System.Diagnostics.CodeAnalysis; using System.Reactive; using System.Reactive.Linq; using System.Reactive.Subjects; @@ -21,25 +22,12 @@ namespace ReactiveUI /// (i.e. you can call RaiseAndSetIfChanged). /// /// The view model type. + [SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:FileMayOnlyContainASingleType", Justification = "Classes with the same class names within.")] public class ReactivePreferenceActivity : ReactivePreferenceActivity, IViewFor, ICanActivate where TViewModel : class { private TViewModel _viewModel; - /// - public TViewModel ViewModel - { - get => _viewModel; - set => this.RaiseAndSetIfChanged(ref _viewModel, value); - } - - /// - object IViewFor.ViewModel - { - get => _viewModel; - set => _viewModel = (TViewModel)value; - } - /// /// Initializes a new instance of the class. /// @@ -56,100 +44,33 @@ namespace ReactiveUI : base(handle, ownership) { } + + /// + public TViewModel ViewModel + { + get => _viewModel; + set => this.RaiseAndSetIfChanged(ref _viewModel, value); + } + + /// + object IViewFor.ViewModel + { + get => _viewModel; + set => _viewModel = (TViewModel)value; + } } /// /// This is an Activity that is both an Activity and has ReactiveObject powers /// (i.e. you can call RaiseAndSetIfChanged). /// + [SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:FileMayOnlyContainASingleType", Justification = "Classes with the same class names within.")] public class ReactivePreferenceActivity : PreferenceActivity, IReactiveObject, IReactiveNotifyPropertyChanged, IHandleObservableErrors { private readonly Subject _activated = new Subject(); private readonly Subject _deactivated = new Subject(); private readonly Subject> _activityResult = new Subject>(); - /// - public event PropertyChangingEventHandler PropertyChanging - { - add => PropertyChangingEventManager.AddHandler(this, value); - remove => PropertyChangingEventManager.RemoveHandler(this, value); - } - - /// - void IReactiveObject.RaisePropertyChanging(PropertyChangingEventArgs args) - { - PropertyChangingEventManager.DeliverEvent(this, args); - } - - /// - public event PropertyChangedEventHandler PropertyChanged - { - add => PropertyChangedEventManager.AddHandler(this, value); - remove => PropertyChangedEventManager.RemoveHandler(this, value); - } - - /// - void IReactiveObject.RaisePropertyChanged(PropertyChangedEventArgs args) - { - PropertyChangedEventManager.DeliverEvent(this, args); - } - - /// - /// Represents an Observable that fires *before* a property is about to - /// be changed. - /// - public IObservable> Changing - { - get => this.GetChangingObservable(); - } - - /// - /// Represents an Observable that fires *after* a property has changed. - /// - public IObservable> Changed - { - get => this.GetChangedObservable(); - } - - /// - public IObservable ThrownExceptions - { - get => this.GetThrownExceptionsObservable(); - } - - /// - /// Gets a signal when the activity is activated. - /// - /// - /// The deactivated. - /// - public IObservable Activated - { - get => _activated.AsObservable(); - } - - /// - /// Gets a signal when the activity is deactivated. - /// - /// - /// The deactivated. - /// - public IObservable Deactivated - { - get => _deactivated.AsObservable(); - } - - /// - /// Gets a signal with an activity result. - /// - /// - /// The deactivated. - /// - public IObservable> ActivityResult - { - get => _activityResult.AsObservable(); - } - /// /// Initializes a new instance of the class. /// @@ -167,6 +88,53 @@ namespace ReactiveUI { } + /// + public event PropertyChangingEventHandler PropertyChanging + { + add => PropertyChangingEventManager.AddHandler(this, value); + remove => PropertyChangingEventManager.RemoveHandler(this, value); + } + + /// + public event PropertyChangedEventHandler PropertyChanged + { + add => PropertyChangedEventManager.AddHandler(this, value); + remove => PropertyChangedEventManager.RemoveHandler(this, value); + } + + /// + public IObservable> Changing => this.GetChangingObservable(); + + /// + public IObservable> Changed => this.GetChangedObservable(); + + /// + public IObservable ThrownExceptions => this.GetThrownExceptionsObservable(); + + /// + /// Gets a signal when the activity is activated. + /// + /// + /// The deactivated. + /// + public IObservable Activated => _activated.AsObservable(); + + /// + /// Gets a signal when the activity is deactivated. + /// + /// + /// The deactivated. + /// + public IObservable Deactivated => _deactivated.AsObservable(); + + /// + /// Gets a signal with an activity result. + /// + /// + /// The deactivated. + /// + public IObservable> ActivityResult => _activityResult.AsObservable(); + /// /// When this method is called, an object will not fire change /// notifications (neither traditional nor Observable notifications) @@ -176,6 +144,18 @@ namespace ReactiveUI /// notifications. public IDisposable SuppressChangeNotifications() => IReactiveObjectExtensions.SuppressChangeNotifications(this); + /// + void IReactiveObject.RaisePropertyChanging(PropertyChangingEventArgs args) + { + PropertyChangingEventManager.DeliverEvent(this, args); + } + + /// + void IReactiveObject.RaisePropertyChanged(PropertyChangedEventArgs args) + { + PropertyChangedEventManager.DeliverEvent(this, args); + } + /// /// Starts the activity for result asynchronously. /// diff --git a/src/ReactiveUI/Platforms/android/ReactivePreferenceFragment.cs b/src/ReactiveUI/Platforms/android/ReactivePreferenceFragment.cs index 1348eecb..52a8a2dc 100644 --- a/src/ReactiveUI/Platforms/android/ReactivePreferenceFragment.cs +++ b/src/ReactiveUI/Platforms/android/ReactivePreferenceFragment.cs @@ -4,6 +4,7 @@ using System; using System.ComponentModel; +using System.Diagnostics.CodeAnalysis; using System.Reactive; using System.Reactive.Linq; using System.Reactive.Subjects; @@ -17,9 +18,12 @@ namespace ReactiveUI /// (i.e. you can call RaiseAndSetIfChanged). /// /// The view model type. + [SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:FileMayOnlyContainASingleType", Justification = "Classes with the same class names within.")] public class ReactivePreferenceFragment : ReactivePreferenceFragment, IViewFor, ICanActivate where TViewModel : class { + private TViewModel _viewModel; + /// /// Initializes a new instance of the class. /// @@ -37,20 +41,18 @@ namespace ReactiveUI { } - private TViewModel _viewModel; - /// public TViewModel ViewModel { - get { return _viewModel; } - set { this.RaiseAndSetIfChanged(ref _viewModel, value); } + get => _viewModel; + set => this.RaiseAndSetIfChanged(ref _viewModel, value); } /// object IViewFor.ViewModel { - get { return _viewModel; } - set { _viewModel = (TViewModel)value; } + get => _viewModel; + set => _viewModel = (TViewModel)value; } } @@ -58,6 +60,7 @@ namespace ReactiveUI /// This is a PreferenceFragment that is both an Activity and has ReactiveObject powers /// (i.e. you can call RaiseAndSetIfChanged). /// + [SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:FileMayOnlyContainASingleType", Justification = "Classes with the same class names within.")] public class ReactivePreferenceFragment : PreferenceFragment, IReactiveNotifyPropertyChanged, IReactiveObject, IHandleObservableErrors { private readonly Subject _activated = new Subject(); @@ -94,6 +97,28 @@ namespace ReactiveUI remove => PropertyChangedEventManager.RemoveHandler(this, value); } + /// + public IObservable> Changing => this.GetChangingObservable(); + + /// + public IObservable> Changed => this.GetChangedObservable(); + + /// + public IObservable ThrownExceptions => this.GetThrownExceptionsObservable(); + + /// + /// Gets a signal when the fragment is activated. + /// + public IObservable Activated => _activated.AsObservable(); + + /// + /// Gets a signal when the fragment is deactivated. + /// + public IObservable Deactivated => _deactivated.AsObservable(); + + /// + public IDisposable SuppressChangeNotifications() => IReactiveObjectExtensions.SuppressChangeNotifications(this); + /// void IReactiveObject.RaisePropertyChanged(PropertyChangedEventArgs args) { @@ -106,54 +131,6 @@ namespace ReactiveUI PropertyChangingEventManager.DeliverEvent(this, args); } - /// - /// Represents an Observable that fires *before* a property is about to - /// be changed. - /// - public IObservable> Changing - { - get => this.GetChangingObservable(); - } - - /// - /// Represents an Observable that fires *after* a property has changed. - /// - public IObservable> Changed - { - get => this.GetChangedObservable(); - } - - /// - public IObservable ThrownExceptions - { - get => this.GetThrownExceptionsObservable(); - } - - /// - /// Gets a signal when the fragment is activated. - /// - public IObservable Activated - { - get => _activated.AsObservable(); - } - - /// - /// Gets a signal when the fragment is deactivated. - /// - public IObservable Deactivated - { - get => _deactivated.AsObservable(); - } - - /// - /// When this method is called, an object will not fire change - /// notifications (neither traditional nor Observable notifications) - /// until the return value is disposed. - /// - /// An object that, when disposed, reenables change - /// notifications. - public IDisposable SuppressChangeNotifications() => IReactiveObjectExtensions.SuppressChangeNotifications(this); - /// public override void OnPause() { diff --git a/src/ReactiveUI/Platforms/android/ReactiveViewHost.cs b/src/ReactiveUI/Platforms/android/ReactiveViewHost.cs new file mode 100644 index 00000000..2d66b5e8 --- /dev/null +++ b/src/ReactiveUI/Platforms/android/ReactiveViewHost.cs @@ -0,0 +1,152 @@ +// 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; +using System.ComponentModel; +using System.Diagnostics.CodeAnalysis; +using System.Linq; +using System.Reflection; +using System.Runtime.Serialization; +using Android.Content; +using Android.Views; + +namespace ReactiveUI +{ + /// + /// A class that implements the Android ViewHolder pattern with a + /// ViewModel. Use it along with GetViewHost. + /// + /// The view model type. + public abstract class ReactiveViewHost : LayoutViewHost, IViewFor, IReactiveNotifyPropertyChanged>, IReactiveObject + where TViewModel : class, IReactiveObject + { + /// + /// All public properties. + /// + [SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1401: Field should be private", Justification = "Legacy reasons")] + [SuppressMessage("Design", "CA1051: Do not declare visible instance fields", Justification = "Legacy reasons")] + [IgnoreDataMember] + protected Lazy allPublicProperties; + + private TViewModel _viewModel; + + /// + /// Initializes a new instance of the class. + /// + /// The CTX. + /// The layout identifier. + /// The parent. + /// if set to true [attach to root]. + /// if set to true [perform automatic wireup]. + protected ReactiveViewHost(Context ctx, int layoutId, ViewGroup parent, bool attachToRoot = false, bool performAutoWireup = true) + : base(ctx, layoutId, parent, attachToRoot, performAutoWireup) + { + SetupRxObj(); + } + + /// + /// Initializes a new instance of the class. + /// + protected ReactiveViewHost() + { + SetupRxObj(); + } + + /// + public event PropertyChangedEventHandler PropertyChanged + { + add { PropertyChangedEventManager.AddHandler(this, value); } + remove { PropertyChangedEventManager.RemoveHandler(this, value); } + } + + /// + public event PropertyChangingEventHandler PropertyChanging + { + add { PropertyChangingEventManager.AddHandler(this, value); } + remove { PropertyChangingEventManager.RemoveHandler(this, value); } + } + + /// + public TViewModel ViewModel + { + get { return _viewModel; } + set { this.RaiseAndSetIfChanged(ref _viewModel, value); } + } + + /// + object IViewFor.ViewModel + { + get { return _viewModel; } + set { _viewModel = (TViewModel)value; } + } + + /// + [IgnoreDataMember] + public IObservable>> Changing + { + get { return this.GetChangingObservable(); } + } + + /// + [IgnoreDataMember] + public IObservable>> Changed + { + get { return this.GetChangedObservable(); } + } + + /// + /// Gets the thrown exceptions. + /// + [IgnoreDataMember] + public IObservable ThrownExceptions + { + get { return this.GetThrownExceptionsObservable(); } + } + + /// + /// When this method is called, an object will not fire change + /// notifications (neither traditional nor Observable notifications) + /// until the return value is disposed. + /// + /// An object that, when disposed, reenables change + /// notifications. + public IDisposable SuppressChangeNotifications() + { + return IReactiveObjectExtensions.SuppressChangeNotifications(this); + } + + /// + /// Gets a value indicating if change notifications are enabled. + /// + /// A value indicating if change notifications are on or off. + public bool AreChangeNotificationsEnabled() + { + return IReactiveObjectExtensions.AreChangeNotificationsEnabled(this); + } + + /// + void IReactiveObject.RaisePropertyChanging(PropertyChangingEventArgs args) + { + PropertyChangingEventManager.DeliverEvent(this, args); + } + + /// + void IReactiveObject.RaisePropertyChanged(PropertyChangedEventArgs args) + { + PropertyChangedEventManager.DeliverEvent(this, args); + } + + [OnDeserialized] + private void SetupRxObj(StreamingContext sc) + { + SetupRxObj(); + } + + private void SetupRxObj() + { + allPublicProperties = new Lazy(() => + GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance).ToArray()); + } + } +} diff --git a/src/ReactiveUI/Platforms/android/ResolveStrategy.cs b/src/ReactiveUI/Platforms/android/ResolveStrategy.cs index 84d6d06a..49ff2769 100644 --- a/src/ReactiveUI/Platforms/android/ResolveStrategy.cs +++ b/src/ReactiveUI/Platforms/android/ResolveStrategy.cs @@ -4,6 +4,9 @@ namespace ReactiveUI { + /// + /// Extension methods associated with the ControlFetcher class. + /// public static partial class ControlFetcherMixin { /// diff --git a/src/ReactiveUI/Platforms/android/UsbManagerExtensions.cs b/src/ReactiveUI/Platforms/android/UsbManagerExtensions.cs index 92eb046d..2a99a946 100644 --- a/src/ReactiveUI/Platforms/android/UsbManagerExtensions.cs +++ b/src/ReactiveUI/Platforms/android/UsbManagerExtensions.cs @@ -16,7 +16,7 @@ namespace ReactiveUI /// public static class UsbManagerExtensions { - private const string ACTION_USB_PERMISSION = "com.reactiveui.USB_PERMISSION"; + private const string ActionUsbPermission = "com.reactiveui.USB_PERMISSION"; /// /// Requests temporary permission for the given package to access the device. @@ -31,9 +31,9 @@ namespace ReactiveUI return Observable.Create(observer => { var usbPermissionReceiver = new UsbDevicePermissionReceiver(observer, device); - context.RegisterReceiver(usbPermissionReceiver, new IntentFilter(ACTION_USB_PERMISSION)); + context.RegisterReceiver(usbPermissionReceiver, new IntentFilter(ActionUsbPermission)); - var intent = PendingIntent.GetBroadcast(context, 0, new Intent(ACTION_USB_PERMISSION), 0); + var intent = PendingIntent.GetBroadcast(context, 0, new Intent(ActionUsbPermission), 0); manager.RequestPermission(device, intent); return Disposable.Create(() => context.UnregisterReceiver(usbPermissionReceiver)); @@ -53,9 +53,9 @@ namespace ReactiveUI return Observable.Create(observer => { var usbPermissionReceiver = new UsbAccessoryPermissionReceiver(observer, accessory); - context.RegisterReceiver(usbPermissionReceiver, new IntentFilter(ACTION_USB_PERMISSION)); + context.RegisterReceiver(usbPermissionReceiver, new IntentFilter(ActionUsbPermission)); - var intent = PendingIntent.GetBroadcast(context, 0, new Intent(ACTION_USB_PERMISSION), 0); + var intent = PendingIntent.GetBroadcast(context, 0, new Intent(ActionUsbPermission), 0); manager.RequestPermission(accessory, intent); return Disposable.Create(() => context.UnregisterReceiver(usbPermissionReceiver)); diff --git a/src/ReactiveUI/Platforms/android/ViewMixins.cs b/src/ReactiveUI/Platforms/android/ViewMixins.cs new file mode 100644 index 00000000..4d4184af --- /dev/null +++ b/src/ReactiveUI/Platforms/android/ViewMixins.cs @@ -0,0 +1,52 @@ +// 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 Android.Views; + +namespace ReactiveUI +{ + /// + /// Default methods for . + /// + public static class ViewMixins + { + internal const int ViewHostTag = -4222; + + /// + /// Gets the ViewHost associated with a given View by accessing the + /// Tag of the View. + /// + /// The layout view host type. + /// The view. + /// The view host. + public static T GetViewHost(this View @this) + where T : ILayoutViewHost + { + var tagData = @this.GetTag(ViewHostTag); + if (tagData != null) + { + return tagData.ToNetObject(); + } + + return default(T); + } + + /// + /// Gets the ViewHost associated with a given View by accessing the + /// Tag of the View. + /// + /// The view. + /// The view host. + public static ILayoutViewHost GetViewHost(this View @this) + { + var tagData = @this.GetTag(ViewHostTag); + if (tagData != null) + { + return tagData.ToNetObject(); + } + + return null; + } + } +} diff --git a/src/ReactiveUI/Platforms/android/WireUpResourceAttribute.cs b/src/ReactiveUI/Platforms/android/WireUpResourceAttribute.cs new file mode 100644 index 00000000..9581c43b --- /dev/null +++ b/src/ReactiveUI/Platforms/android/WireUpResourceAttribute.cs @@ -0,0 +1,32 @@ +using System; + +namespace ReactiveUI +{ + /// + /// Attribute that marks a resource for wiring. + /// + [AttributeUsage(AttributeTargets.All)] + public class WireUpResourceAttribute : Attribute + { + /// + /// Initializes a new instance of the class. + /// + public WireUpResourceAttribute() + { + } + + /// + /// Initializes a new instance of the class. + /// + /// Name of the resource. + public WireUpResourceAttribute(string resourceName) + { + ResourceNameOverride = resourceName; + } + + /// + /// Gets the resource name override. + /// + public string ResourceNameOverride { get; } + } +} diff --git a/src/ReactiveUI/Platforms/apple-common/JsonSuspensionDriver.cs b/src/ReactiveUI/Platforms/apple-common/AppSupportJsonSuspensionDriver.cs similarity index 96% rename from src/ReactiveUI/Platforms/apple-common/JsonSuspensionDriver.cs rename to src/ReactiveUI/Platforms/apple-common/AppSupportJsonSuspensionDriver.cs index c038e63d..d674c18f 100644 --- a/src/ReactiveUI/Platforms/apple-common/JsonSuspensionDriver.cs +++ b/src/ReactiveUI/Platforms/apple-common/AppSupportJsonSuspensionDriver.cs @@ -75,7 +75,7 @@ namespace ReactiveUI } } - private string CreateAppDirectory(NSSearchPathDirectory targetDir, string subDir = "Data") + private static string CreateAppDirectory(NSSearchPathDirectory targetDir, string subDir = "Data") { NSError err; diff --git a/src/ReactiveUI/Platforms/apple-common/AutoLayoutViewModelViewHost.cs b/src/ReactiveUI/Platforms/apple-common/AutoLayoutViewModelViewHost.cs deleted file mode 100644 index 8712ec32..00000000 --- a/src/ReactiveUI/Platforms/apple-common/AutoLayoutViewModelViewHost.cs +++ /dev/null @@ -1,33 +0,0 @@ -// 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; -#if UIKIT -using NSView = UIKit.UIView; -#else -using AppKit; -#endif - -namespace ReactiveUI -{ - /// - /// Use this class instead of when - /// taking advantage of Auto Layout. This will automatically wire - /// up edge constraints for you from the parent view (the target) - /// to the child subview. - /// - [Obsolete("Use ViewModelViewHost instead. This class will be removed in a future release.")] - public class AutoLayoutViewModelViewHostLegacy : ViewModelViewHostLegacy - { - /// - /// Initializes a new instance of the class. - /// - /// The target ns view. - public AutoLayoutViewModelViewHostLegacy(NSView targetView) - : base(targetView) - { - AddAutoLayoutConstraintsToSubView = true; - } - } -} diff --git a/src/ReactiveUI/Platforms/apple-common/BlockObserveValueDelegate.cs b/src/ReactiveUI/Platforms/apple-common/BlockObserveValueDelegate.cs new file mode 100644 index 00000000..85e96665 --- /dev/null +++ b/src/ReactiveUI/Platforms/apple-common/BlockObserveValueDelegate.cs @@ -0,0 +1,31 @@ +// 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; +using System.Linq; +using System.Linq.Expressions; +using System.Reactive.Disposables; +using System.Reactive.Linq; +using System.Reflection; +using System.Runtime.InteropServices; +using Foundation; +using Splat; + +namespace ReactiveUI +{ + internal class BlockObserveValueDelegate : NSObject + { + private Action _block; + + public BlockObserveValueDelegate(Action block) + { + _block = block; + } + + public override void ObserveValue(NSString keyPath, NSObject ofObject, NSDictionary change, IntPtr context) + { + _block(keyPath, ofObject, change); + } + } +} diff --git a/src/ReactiveUI/Platforms/apple-common/Converters/DateTimeToNSDateConverter.cs b/src/ReactiveUI/Platforms/apple-common/Converters/DateTimeNSDateConverter.cs similarity index 87% rename from src/ReactiveUI/Platforms/apple-common/Converters/DateTimeToNSDateConverter.cs rename to src/ReactiveUI/Platforms/apple-common/Converters/DateTimeNSDateConverter.cs index 9f7c0b5a..2b961380 100644 --- a/src/ReactiveUI/Platforms/apple-common/Converters/DateTimeToNSDateConverter.cs +++ b/src/ReactiveUI/Platforms/apple-common/Converters/DateTimeNSDateConverter.cs @@ -10,10 +10,9 @@ namespace ReactiveUI /// /// Binding Type Converter for DateTime to NSDateTime. /// - public class DateTimeNSDateConverter : - IBindingTypeConverter + public class DateTimeNSDateConverter : IBindingTypeConverter { - internal static Lazy Instance = new Lazy(); + internal static Lazy Instance { get; } = new Lazy(); /// public int GetAffinityForObjects(Type fromType, Type toType) diff --git a/src/ReactiveUI/Platforms/apple-common/IndexNormalizer.cs b/src/ReactiveUI/Platforms/apple-common/IndexNormalizer.cs index eb613b5a..a2b68684 100644 --- a/src/ReactiveUI/Platforms/apple-common/IndexNormalizer.cs +++ b/src/ReactiveUI/Platforms/apple-common/IndexNormalizer.cs @@ -77,7 +77,7 @@ namespace ReactiveUI case UpdateType.Add: return CalculateAdditionIndex(updates, 0, updates.Count, updateIndex); case UpdateType.Delete: - return CalculateDeletionIndex(updates, 0, updates.Count, updateIndex, updates[updateIndex].Index); + return CalculateDeletionIndex(updates, 0, updateIndex, updates[updateIndex].Index); default: throw new NotSupportedException(); } @@ -94,7 +94,7 @@ namespace ReactiveUI private static int CalculateAdditionIndex(IList updates, int start, int count, int updateIndex) { var update = updates[updateIndex]; - Debug.Assert(update.Type == UpdateType.Add); + Debug.Assert(update.Type == UpdateType.Add, "Must be adding items"); var originalIndex = update.Index; var runningCalculation = originalIndex; @@ -133,7 +133,7 @@ namespace ReactiveUI // Io = the deletion's original index (as specified by client code) // Nd = the number of prior deletion updates whose original index is <= the running (calculated) index of the update whose index is being calculated // Na = the number of prior addition updates whose original index is <= the running (calculated) index of the update whose index is being calculated - private static int CalculateDeletionIndex(IList updates, int start, int count, int deletionIndex, int originalIndex) + private static int CalculateDeletionIndex(IList updates, int start, int deletionIndex, int originalIndex) { var runningCalculation = originalIndex; diff --git a/src/ReactiveUI/Platforms/apple-common/KVOObservableForProperty.cs b/src/ReactiveUI/Platforms/apple-common/KVOObservableForProperty.cs index 26299fd9..26cddc2d 100644 --- a/src/ReactiveUI/Platforms/apple-common/KVOObservableForProperty.cs +++ b/src/ReactiveUI/Platforms/apple-common/KVOObservableForProperty.cs @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information. using System; +using System.Globalization; using System.Linq; using System.Linq.Expressions; using System.Reactive.Disposables; @@ -96,7 +97,7 @@ namespace ReactiveUI }); } - private string FindCocoaNameFromNetName(Type senderType, string propertyName) + private static string FindCocoaNameFromNetName(Type senderType, string propertyName) { bool propIsBoolean = false; @@ -131,22 +132,7 @@ namespace ReactiveUI propertyName = "Is" + propertyName; } - return char.ToLowerInvariant(propertyName[0]).ToString() + propertyName.Substring(1); - } - } - - internal class BlockObserveValueDelegate : NSObject - { - private Action _block; - - public BlockObserveValueDelegate(Action block) - { - _block = block; - } - - public override void ObserveValue(NSString keyPath, NSObject ofObject, NSDictionary change, IntPtr context) - { - _block(keyPath, ofObject, change); + return char.ToLowerInvariant(propertyName[0]).ToString(CultureInfo.InvariantCulture) + propertyName.Substring(1); } } } diff --git a/src/ReactiveUI/Platforms/apple-common/ObservableForPropertyBase.cs b/src/ReactiveUI/Platforms/apple-common/ObservableForPropertyBase.cs index 01e43796..152ff090 100644 --- a/src/ReactiveUI/Platforms/apple-common/ObservableForPropertyBase.cs +++ b/src/ReactiveUI/Platforms/apple-common/ObservableForPropertyBase.cs @@ -93,17 +93,11 @@ namespace ReactiveUI { var control = (UIControl)sender; - EventHandler handler = (s, e) => - { - subj.OnNext(new ObservedChange(sender, expression)); - }; + EventHandler handler = (s, e) => subj.OnNext(new ObservedChange(sender, expression)); control.AddTarget(handler, evt); - return Disposable.Create(() => - { - control.RemoveTarget(handler, evt); - }); + return Disposable.Create(() => control.RemoveTarget(handler, evt)); }); } #endif @@ -119,10 +113,10 @@ namespace ReactiveUI { return Observable.Create>(subj => { - var handle = NSNotificationCenter.DefaultCenter.AddObserver(notification, (e) => - { - subj.OnNext(new ObservedChange(sender, expression)); - }, sender); + var handle = NSNotificationCenter.DefaultCenter.AddObserver( + notification, + _ => subj.OnNext(new ObservedChange(sender, expression)), + sender); return Disposable.Create(() => { @@ -165,14 +159,14 @@ namespace ReactiveUI _config[type] = typeProperties; } - var info = new ObservablePropertyInfo { Affinity = affinity, CreateObservable = createObservable }; - typeProperties[property] = info; + typeProperties[property] = new ObservablePropertyInfo { Affinity = affinity, CreateObservable = createObservable }; } internal class ObservablePropertyInfo { - public int Affinity; - public Func>> CreateObservable; + public int Affinity { get; set; } + + public Func>> CreateObservable { get; set; } } } } diff --git a/src/ReactiveUI/Platforms/apple-common/ReactiveControl.cs b/src/ReactiveUI/Platforms/apple-common/ReactiveControl.cs index 7e7e4bd9..2a65638c 100644 --- a/src/ReactiveUI/Platforms/apple-common/ReactiveControl.cs +++ b/src/ReactiveUI/Platforms/apple-common/ReactiveControl.cs @@ -4,6 +4,7 @@ using System; using System.ComponentModel; +using System.Diagnostics.CodeAnalysis; using System.Reactive; using System.Reactive.Concurrency; using System.Reactive.Linq; @@ -24,9 +25,13 @@ namespace ReactiveUI /// This is a UIControl that is both and UIControl and has a ReactiveObject powers /// (i.e. you can call RaiseAndSetIfChanged). /// - /// The view model type. + [SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:FileMayOnlyContainASingleType", Justification = "Classes with the same class names within.")] + [SuppressMessage("Design", "CA1010: Implement generic IEnumerable", Justification = "UI Kit exposes IEnumerable")] public class ReactiveControl : UIControl, IReactiveNotifyPropertyChanged, IHandleObservableErrors, IReactiveObject, ICanActivate, ICanForceManualActivation { + private Subject _deactivated = new Subject(); + private Subject _activated = new Subject(); + /// /// Initializes a new instance of the class. /// @@ -84,52 +89,25 @@ namespace ReactiveUI remove => PropertyChangedEventManager.RemoveHandler(this, value); } - /// - /// Represents an Observable that fires *before* a property is about to - /// be changed. - /// + /// public IObservable> Changing => this.GetChangingObservable(); - /// - /// Represents an Observable that fires *after* a property has changed. - /// + /// public IObservable> Changed => this.GetChangedObservable(); - /// - void IReactiveObject.RaisePropertyChanging(PropertyChangingEventArgs args) - { - PropertyChangingEventManager.DeliverEvent(this, args); - } - - /// - void IReactiveObject.RaisePropertyChanged(PropertyChangedEventArgs args) - { - PropertyChangedEventManager.DeliverEvent(this, args); - } - - /// - /// When this method is called, an object will not fire change - /// notifications (neither traditional nor Observable notifications) - /// until the return value is disposed. - /// - /// An object that, when disposed, reenables change - /// notifications. - public IDisposable SuppressChangeNotifications() - { - return IReactiveObjectExtensions.SuppressChangeNotifications(this); - } - /// public IObservable ThrownExceptions => this.GetThrownExceptionsObservable(); - private Subject _activated = new Subject(); - - /// + /// + /// Gets a observable when the control is activated. + /// + [SuppressMessage("Design", "CS0108: member hides inherited member", Justification = "Different type.")] public IObservable Activated => _activated.AsObservable(); - private Subject _deactivated = new Subject(); - - /// + /// + /// Gets a observable that occurrs when the control is deactivated. + /// + [SuppressMessage("Design", "CS0108: member hides inherited member", Justification = "Different type.")] public IObservable Deactivated => _deactivated.AsObservable(); #if UIKIT @@ -154,6 +132,30 @@ namespace ReactiveUI RxApp.MainThreadScheduler.Schedule(() => (activate ? _activated : _deactivated).OnNext(Unit.Default)); } + + /// + void IReactiveObject.RaisePropertyChanging(PropertyChangingEventArgs args) + { + PropertyChangingEventManager.DeliverEvent(this, args); + } + + /// + void IReactiveObject.RaisePropertyChanged(PropertyChangedEventArgs args) + { + PropertyChangedEventManager.DeliverEvent(this, args); + } + + /// + /// When this method is called, an object will not fire change + /// notifications (neither traditional nor Observable notifications) + /// until the return value is disposed. + /// + /// An object that, when disposed, reenables change + /// notifications. + public IDisposable SuppressChangeNotifications() + { + return IReactiveObjectExtensions.SuppressChangeNotifications(this); + } } /// @@ -161,20 +163,22 @@ namespace ReactiveUI /// (i.e. you can call RaiseAndSetIfChanged). /// /// The view model type. + [SuppressMessage("Design", "CA1010: Implement generic IEnumerable", Justification = "UI Kit exposes IEnumerable")] + [SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:FileMayOnlyContainASingleType", Justification = "Classes with the same class names within.")] public abstract class ReactiveControl : ReactiveControl, IViewFor where TViewModel : class { private TViewModel _viewModel; /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// protected ReactiveControl() { } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The coder. protected ReactiveControl(NSCoder c) @@ -183,7 +187,7 @@ namespace ReactiveUI } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The object flag. protected ReactiveControl(NSObjectFlag f) @@ -192,7 +196,7 @@ namespace ReactiveUI } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The pointer handle. protected ReactiveControl(IntPtr handle) @@ -201,7 +205,7 @@ namespace ReactiveUI } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The frame. protected ReactiveControl(CGRect frame) diff --git a/src/ReactiveUI/Platforms/apple-common/ReactiveImageView.cs b/src/ReactiveUI/Platforms/apple-common/ReactiveImageView.cs index 819f04ec..6ba99e96 100644 --- a/src/ReactiveUI/Platforms/apple-common/ReactiveImageView.cs +++ b/src/ReactiveUI/Platforms/apple-common/ReactiveImageView.cs @@ -4,6 +4,7 @@ using System; using System.ComponentModel; +using System.Diagnostics.CodeAnalysis; using System.Reactive; using System.Reactive.Concurrency; using System.Reactive.Linq; @@ -26,6 +27,8 @@ namespace ReactiveUI /// This is an ImageView that is both and ImageView and has a ReactiveObject powers /// (i.e. you can call RaiseAndSetIfChanged). /// + [SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:FileMayOnlyContainASingleType", Justification = "Classes with the same class names within.")] + [SuppressMessage("Design", "CA1010: Implement generic IEnumerable", Justification = "UI Kit exposes IEnumerable")] public abstract class ReactiveImageView : NSImageView, IReactiveNotifyPropertyChanged, IHandleObservableErrors, IReactiveObject, ICanActivate, ICanForceManualActivation { private Subject _activated = new Subject(); @@ -113,20 +116,17 @@ namespace ReactiveUI public IObservable ThrownExceptions => this.GetThrownExceptionsObservable(); /// + [SuppressMessage("Design", "CS0108: member hides inherited member", Justification = "Different type.")] public IObservable Activated => _activated.AsObservable(); /// + [SuppressMessage("Design", "CS0108: member hides inherited member", Justification = "Different type.")] public IObservable Deactivated => _deactivated.AsObservable(); - /// - /// Represents an Observable that fires *before* a property is about to - /// be changed. - /// + /// public IObservable> Changing => this.GetChangingObservable(); - /// - /// Represents an Observable that fires *after* a property has changed. - /// + /// public IObservable> Changed => this.GetChangedObservable(); /// @@ -176,20 +176,22 @@ namespace ReactiveUI /// (i.e. you can call RaiseAndSetIfChanged). /// /// The view model type. + [SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:FileMayOnlyContainASingleType", Justification = "Classes with the same class names within.")] + [SuppressMessage("Design", "CA1010: Implement generic IEnumerable", Justification = "UI Kit exposes IEnumerable")] public abstract class ReactiveImageView : ReactiveImageView, IViewFor where TViewModel : class { private TViewModel _viewModel; /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// protected ReactiveImageView() { } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The frame. protected ReactiveImageView(CGRect frame) @@ -199,7 +201,7 @@ namespace ReactiveUI #if UIKIT /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The image. protected ReactiveImageView(NSImage image) @@ -208,7 +210,7 @@ namespace ReactiveUI } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The object flag. protected ReactiveImageView(NSObjectFlag t) @@ -217,7 +219,7 @@ namespace ReactiveUI } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The image. /// The highlighted image. @@ -227,7 +229,7 @@ namespace ReactiveUI } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The coder. protected ReactiveImageView(NSCoder coder) @@ -237,7 +239,7 @@ namespace ReactiveUI #endif /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The pointer. protected ReactiveImageView(IntPtr handle) diff --git a/src/ReactiveUI/Platforms/apple-common/ReactiveSplitViewController.cs b/src/ReactiveUI/Platforms/apple-common/ReactiveSplitViewController.cs index 37d02210..b746194d 100644 --- a/src/ReactiveUI/Platforms/apple-common/ReactiveSplitViewController.cs +++ b/src/ReactiveUI/Platforms/apple-common/ReactiveSplitViewController.cs @@ -4,6 +4,7 @@ using System; using System.ComponentModel; +using System.Diagnostics.CodeAnalysis; using System.Reactive; using System.Reactive.Linq; using System.Reactive.Subjects; @@ -23,8 +24,9 @@ namespace ReactiveUI /// This is a View that is both a NSSplitViewController and has ReactiveObject powers /// (i.e. you can call RaiseAndSetIfChanged). /// - public abstract class ReactiveSplitViewController : NSSplitViewController, - IReactiveNotifyPropertyChanged, IHandleObservableErrors, IReactiveObject, ICanActivate + [SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:FileMayOnlyContainASingleType", Justification = "Classes with the same class names within.")] + [SuppressMessage("Design", "CA1010: Implement generic IEnumerable", Justification = "UI Kit exposes IEnumerable")] + public abstract class ReactiveSplitViewController : NSSplitViewController, IReactiveNotifyPropertyChanged, IHandleObservableErrors, IReactiveObject, ICanActivate { private readonly Subject _activated = new Subject(); private readonly Subject _deactivated = new Subject(); @@ -38,7 +40,6 @@ namespace ReactiveUI protected ReactiveSplitViewController(string nibName, NSBundle bundle) : base(nibName, bundle) { - SetupRxObj(); } #endif @@ -49,7 +50,6 @@ namespace ReactiveUI protected ReactiveSplitViewController(IntPtr handle) : base(handle) { - SetupRxObj(); } /// @@ -59,7 +59,6 @@ namespace ReactiveUI protected ReactiveSplitViewController(NSObjectFlag t) : base(t) { - SetupRxObj(); } /// @@ -69,7 +68,6 @@ namespace ReactiveUI protected ReactiveSplitViewController(NSCoder coder) : base(coder) { - SetupRxObj(); } /// @@ -77,7 +75,6 @@ namespace ReactiveUI /// protected ReactiveSplitViewController() { - SetupRxObj(); } /// @@ -94,15 +91,10 @@ namespace ReactiveUI remove => PropertyChangedEventManager.RemoveHandler(this, value); } - /// - /// Represents an Observable that fires *before* a property is about to - /// be changed. - /// + /// public IObservable> Changing => this.GetChangingObservable(); - /// - /// Represents an Observable that fires *after* a property has changed. - /// + /// public IObservable> Changed => this.GetChangedObservable(); /// @@ -172,10 +164,6 @@ namespace ReactiveUI this.ActivateSubviews(false); } #endif - - private void SetupRxObj() - { - } } /// @@ -183,6 +171,8 @@ namespace ReactiveUI /// (i.e. you can call RaiseAndSetIfChanged). /// /// The view model type. + [SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:FileMayOnlyContainASingleType", Justification = "Classes with the same class names within.")] + [SuppressMessage("Design", "CA1010: Implement generic IEnumerable", Justification = "UI Kit exposes IEnumerable")] public abstract class ReactiveSplitViewController : ReactiveSplitViewController, IViewFor where TViewModel : class { diff --git a/src/ReactiveUI/Platforms/apple-common/ReactiveNSView.cs b/src/ReactiveUI/Platforms/apple-common/ReactiveView.cs similarity index 91% rename from src/ReactiveUI/Platforms/apple-common/ReactiveNSView.cs rename to src/ReactiveUI/Platforms/apple-common/ReactiveView.cs index 442b6c28..1cacb9fc 100644 --- a/src/ReactiveUI/Platforms/apple-common/ReactiveNSView.cs +++ b/src/ReactiveUI/Platforms/apple-common/ReactiveView.cs @@ -4,6 +4,7 @@ using System; using System.ComponentModel; +using System.Diagnostics.CodeAnalysis; using System.Reactive; using System.Reactive.Concurrency; using System.Reactive.Linq; @@ -24,6 +25,8 @@ namespace ReactiveUI /// This is a View that is both a NSView and has ReactiveObject powers /// (i.e. you can call RaiseAndSetIfChanged). /// + [SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:FileMayOnlyContainASingleType", Justification = "Classes with the same class names within.")] + [SuppressMessage("Design", "CA1010: Implement generic IEnumerable", Justification = "UI Kit exposes IEnumerable")] public class ReactiveView : NSView, IReactiveNotifyPropertyChanged, IHandleObservableErrors, IReactiveObject, ICanActivate, ICanForceManualActivation { private readonly Subject _activated = new Subject(); @@ -95,15 +98,10 @@ namespace ReactiveUI /// public IObservable Deactivated => _deactivated.AsObservable(); - /// - /// Represents an Observable that fires *before* a property is about to - /// be changed. - /// + /// public IObservable> Changing => this.GetChangingObservable(); - /// - /// Represents an Observable that fires *after* a property has changed. - /// + /// public IObservable> Changed => this.GetChangedObservable(); /// @@ -163,6 +161,8 @@ namespace ReactiveUI /// (i.e. you can call RaiseAndSetIfChanged). /// /// The view model type. + [SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:FileMayOnlyContainASingleType", Justification = "Classes with the same class names within.")] + [SuppressMessage("Design", "CA1010: Implement generic IEnumerable", Justification = "UI Kit exposes IEnumerable")] public abstract class ReactiveView : ReactiveView, IViewFor where TViewModel : class { diff --git a/src/ReactiveUI/Platforms/apple-common/ReactiveNSViewController.cs b/src/ReactiveUI/Platforms/apple-common/ReactiveViewController.cs similarity index 87% rename from src/ReactiveUI/Platforms/apple-common/ReactiveNSViewController.cs rename to src/ReactiveUI/Platforms/apple-common/ReactiveViewController.cs index 4f57ad9e..24b1a8b4 100644 --- a/src/ReactiveUI/Platforms/apple-common/ReactiveNSViewController.cs +++ b/src/ReactiveUI/Platforms/apple-common/ReactiveViewController.cs @@ -4,6 +4,7 @@ using System; using System.ComponentModel; +using System.Diagnostics.CodeAnalysis; using System.Reactive; using System.Reactive.Linq; using System.Reactive.Subjects; @@ -23,8 +24,9 @@ namespace ReactiveUI /// This is a View that is both a NSViewController and has ReactiveObject powers /// (i.e. you can call RaiseAndSetIfChanged). /// - public class ReactiveViewController : NSViewController, - IReactiveNotifyPropertyChanged, IHandleObservableErrors, IReactiveObject, ICanActivate + [SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:FileMayOnlyContainASingleType", Justification = "Classes with the same class names within.")] + [SuppressMessage("Design", "CA1010: Implement generic IEnumerable", Justification = "UI Kit exposes IEnumerable")] + public class ReactiveViewController : NSViewController, IReactiveNotifyPropertyChanged, IHandleObservableErrors, IReactiveObject, ICanActivate { private readonly Subject _activated = new Subject(); private readonly Subject _deactivated = new Subject(); @@ -87,15 +89,10 @@ namespace ReactiveUI remove => PropertyChangedEventManager.RemoveHandler(this, value); } - /// - /// Represents an Observable that fires *before* a property is about to - /// be changed. - /// + /// public IObservable> Changing => this.GetChangingObservable(); - /// - /// Represents an Observable that fires *after* a property has changed. - /// + /// public IObservable> Changed => this.GetChangedObservable(); /// @@ -171,6 +168,8 @@ namespace ReactiveUI /// (i.e. you can call RaiseAndSetIfChanged). /// /// The view model type. + [SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:FileMayOnlyContainASingleType", Justification = "Classes with the same class names within.")] + [SuppressMessage("Design", "CA1010: Implement generic IEnumerable", Justification = "UI Kit exposes IEnumerable")] public abstract class ReactiveViewController : ReactiveViewController, IViewFor where TViewModel : class { @@ -234,27 +233,4 @@ namespace ReactiveUI set => ViewModel = (TViewModel)value; } } - - internal static class UIViewControllerMixins - { - internal static void ActivateSubviews(this NSViewController @this, bool activate) - { - @this.View.ActivateSubviews(activate); - } - - private static void ActivateSubviews(this NSView @this, bool activate) - { - foreach (var view in @this.Subviews) - { - var subview = view as ICanForceManualActivation; - - if (subview != null) - { - subview.Activate(activate); - } - - view.ActivateSubviews(activate); - } - } - } } diff --git a/src/ReactiveUI/Platforms/apple-common/TargetActionCommandBinder.cs b/src/ReactiveUI/Platforms/apple-common/TargetActionCommandBinder.cs index dad7a5fd..86b7976f 100644 --- a/src/ReactiveUI/Platforms/apple-common/TargetActionCommandBinder.cs +++ b/src/ReactiveUI/Platforms/apple-common/TargetActionCommandBinder.cs @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information. using System; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Reactive.Disposables; using System.Reactive.Linq; @@ -38,7 +39,7 @@ namespace ReactiveUI _validTypes = new[] { typeof(UIControl), - }; + }; #else _validTypes = new[] { @@ -108,10 +109,15 @@ namespace ReactiveUI return compDisp; } + /// + public IDisposable BindCommandToObject(ICommand command, object target, IObservable commandParameter, string eventName) + where TEventArgs : EventArgs + { + throw new NotImplementedException(); + } + private class ControlDelegate : NSObject { - public bool IsEnabled { get; set; } - private readonly Action _block; public ControlDelegate(Action block) @@ -119,6 +125,8 @@ namespace ReactiveUI _block = block; } + public bool IsEnabled { get; set; } + [Export("theAction:")] public void TheAction(NSObject sender) { @@ -127,18 +135,12 @@ namespace ReactiveUI #if !UIKIT [Export("validateMenuItem:")] + [SuppressMessage("Redundancy", "CA1801: Redundant parameter", Justification = "Legacy interface")] public bool ValidateMenuItem(NSMenuItem menuItem) { return IsEnabled; } #endif } - - /// - public IDisposable BindCommandToObject(ICommand command, object target, IObservable commandParameter, string eventName) - where TEventArgs : EventArgs - { - throw new NotImplementedException(); - } } } diff --git a/src/ReactiveUI/Platforms/apple-common/UIViewControllerMixins.cs b/src/ReactiveUI/Platforms/apple-common/UIViewControllerMixins.cs new file mode 100644 index 00000000..dc0f1926 --- /dev/null +++ b/src/ReactiveUI/Platforms/apple-common/UIViewControllerMixins.cs @@ -0,0 +1,45 @@ +// 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; +using System.ComponentModel; +using System.Diagnostics.CodeAnalysis; +using System.Reactive; +using System.Reactive.Linq; +using System.Reactive.Subjects; +using Foundation; + +#if UIKIT +using UIKit; +using NSView = UIKit.UIView; +using NSViewController = UIKit.UIViewController; +#else +using AppKit; +#endif + +namespace ReactiveUI +{ + internal static class UIViewControllerMixins + { + internal static void ActivateSubviews(this NSViewController @this, bool activate) + { + @this.View.ActivateSubviews(activate); + } + + private static void ActivateSubviews(this NSView @this, bool activate) + { + foreach (var view in @this.Subviews) + { + var subview = view as ICanForceManualActivation; + + if (subview != null) + { + subview.Activate(activate); + } + + view.ActivateSubviews(activate); + } + } + } +} diff --git a/src/ReactiveUI/Platforms/apple-common/Update.cs b/src/ReactiveUI/Platforms/apple-common/Update.cs index 94a8f2f8..0d3479b9 100644 --- a/src/ReactiveUI/Platforms/apple-common/Update.cs +++ b/src/ReactiveUI/Platforms/apple-common/Update.cs @@ -2,6 +2,8 @@ // 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.Globalization; + namespace ReactiveUI { /// @@ -9,57 +11,27 @@ namespace ReactiveUI /// public sealed class Update { - private readonly UpdateType _type; - private readonly int _index; - private readonly bool _isDuplicate; - private Update(UpdateType type, int index, bool isDuplicate = false) { - _type = type; - _index = index; - _isDuplicate = isDuplicate; + Type = type; + Index = index; + IsDuplicate = isDuplicate; } /// /// Gets the type. /// - public UpdateType Type => _type; + public UpdateType Type { get; } /// /// Gets the index. /// - public int Index => _index; + public int Index { get; } /// /// Gets a value indicating whether this instance is duplicate. /// - public bool IsDuplicate => _isDuplicate; - - /// - public override string ToString() - { - return _type.ToString()[0] + _index.ToString(); - } - - /// - /// Created a duplicate update. - /// - /// The duplicate update. - public Update AsDuplicate() - { - return new Update(_type, _index, isDuplicate: true); - } - - /// - /// Creates an update of the specified type. - /// - /// The type. - /// The index. - /// And update. - public static Update Create(UpdateType type, int index) - { - return new Update(type, index); - } + public bool IsDuplicate { get; } /// /// Creates an update for the added index. @@ -80,5 +52,31 @@ namespace ReactiveUI { return new Update(UpdateType.Delete, index); } + + /// + /// Creates an update of the specified type. + /// + /// The type. + /// The index. + /// And update. + public static Update Create(UpdateType type, int index) + { + return new Update(type, index); + } + + /// + public override string ToString() + { + return Type.ToString()[0] + Index.ToString(CultureInfo.InvariantCulture); + } + + /// + /// Created a duplicate update. + /// + /// The duplicate update. + public Update AsDuplicate() + { + return new Update(Type, Index, isDuplicate: true); + } } } diff --git a/src/ReactiveUI/Platforms/apple-common/ViewModelViewHost.cs b/src/ReactiveUI/Platforms/apple-common/ViewModelViewHost.cs index e18d6b66..35bae9a4 100644 --- a/src/ReactiveUI/Platforms/apple-common/ViewModelViewHost.cs +++ b/src/ReactiveUI/Platforms/apple-common/ViewModelViewHost.cs @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information. using System; +using System.Diagnostics.CodeAnalysis; using System.Reactive.Disposables; using System.Reactive.Linq; @@ -20,6 +21,8 @@ namespace ReactiveUI /// A control which will use Splat dependency injection to determine the View /// to show. It uses. /// + [SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:FileMayOnlyContainASingleType", Justification = "Classes with the same class names within.")] + [SuppressMessage("Design", "CA1010: Implement generic IEnumerable", Justification = "UI Kit exposes IEnumerable")] public class ViewModelViewHost : ReactiveViewController { private readonly SerialDisposable _currentView; @@ -93,6 +96,61 @@ namespace ReactiveUI set => ViewContractObservable = Observable.Return(value); } + /// + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + + if (disposing) + { + _currentView.Dispose(); + _viewContract.Dispose(); + } + } + + private static void Adopt(NSViewController parent, NSViewController child) + { + // ensure the child view fills our entire frame + child.View.Frame = parent.View.Bounds; +#if UIKIT + child.View.AutoresizingMask = UIViewAutoresizing.FlexibleWidth | UIViewAutoresizing.FlexibleHeight; +#else + child.View.AutoresizingMask = NSViewResizingMask.WidthSizable | NSViewResizingMask.HeightSizable; +#endif + child.View.TranslatesAutoresizingMaskIntoConstraints = true; + + parent.AddChildViewController(child); + +#if UIKIT + var parentAlreadyVisible = parent.IsViewLoaded && parent.View.Window != null; + + if (parentAlreadyVisible) + { + child.BeginAppearanceTransition(true, false); + } +#endif + + parent.View.AddSubview(child.View); + +#if UIKIT + if (parentAlreadyVisible) + { + child.EndAppearanceTransition(); + } + + child.DidMoveToParentViewController(parent); +#endif + } + + private static void Disown(NSViewController child) + { +#if UIKIT + child.WillMoveToParentViewController(null); +#endif + child.View.RemoveFromSuperview(); + child.RemoveFromParentViewController(); + } + private void Initialize() { var viewChange = Observable @@ -151,195 +209,5 @@ namespace ReactiveUI .ObserveOn(RxApp.MainThreadScheduler) .Subscribe(x => Adopt(this, x)); } - - /// - protected override void Dispose(bool disposing) - { - base.Dispose(disposing); - - if (disposing) - { - _currentView.Dispose(); - _viewContract.Dispose(); - } - } - - private static void Adopt(NSViewController parent, NSViewController child) - { - // ensure the child view fills our entire frame - child.View.Frame = parent.View.Bounds; -#if UIKIT - child.View.AutoresizingMask = UIViewAutoresizing.FlexibleWidth | UIViewAutoresizing.FlexibleHeight; -#else - child.View.AutoresizingMask = NSViewResizingMask.WidthSizable | NSViewResizingMask.HeightSizable; -#endif - child.View.TranslatesAutoresizingMaskIntoConstraints = true; - - parent.AddChildViewController(child); - -#if UIKIT - var parentAlreadyVisible = parent.IsViewLoaded && parent.View.Window != null; - - if (parentAlreadyVisible) - { - child.BeginAppearanceTransition(true, false); - } -#endif - - parent.View.AddSubview(child.View); - -#if UIKIT - if (parentAlreadyVisible) - { - child.EndAppearanceTransition(); - } - - child.DidMoveToParentViewController(parent); -#endif - } - - private static void Disown(NSViewController child) - { -#if UIKIT - child.WillMoveToParentViewController(null); -#endif - child.View.RemoveFromSuperview(); - child.RemoveFromParentViewController(); - } - } - - /// - /// ViewModelViewHost is a helper class that will connect a ViewModel - /// to an arbitrary NSView and attempt to load the View for the current - /// ViewModel as a child view of the target. - /// - /// This is a bit different than the XAML's ViewModelViewHost in the sense - /// that this isn't a Control itself, it only manipulates other Views. - /// - [Obsolete("Use ViewModelViewHost instead. This class will be removed in a later release.")] - public class ViewModelViewHostLegacy : ReactiveObject - { -#pragma warning disable 1584, 1711, 1572, 1581, 1580 - /// - /// Gets or sets a value indicating whether this - /// will automatically create Auto Layout constraints tying the sub view to the parent view. - /// - /// true if add layout contraints to sub view; otherwise, false. -#pragma warning restore 1584, 1711, 1572, 1581, 1580 - public bool AddAutoLayoutConstraintsToSubView { get; set; } - -#pragma warning disable SA1600 // Elements should be documented - public ViewModelViewHostLegacy(NSView targetView) - { - if (targetView == null) - { - throw new ArgumentNullException(nameof(targetView)); - } - - NSView viewLastAdded = null; - ViewContractObservable = Observable.Default; - - var vmAndContract = Observable.CombineLatest( - this.WhenAny(x => x.ViewModel, x => x.Value), - this.WhenAnyObservable(x => x.ViewContractObservable), - (vm, contract) => new { ViewModel = vm, Contract = contract, }); - - vmAndContract.Subscribe(x => - { - if (viewLastAdded != null) - { - viewLastAdded.RemoveFromSuperview(); - } - - if (ViewModel == null) - { - if (DefaultContent != null) - { - targetView.AddSubview(DefaultContent.View); - } - - return; - } - - // get an instance of the view controller for the supplied VM + Contract - var viewLocator = ViewLocator ?? ReactiveUI.ViewLocator.Current; - var viewController = viewLocator.ResolveView(x.ViewModel, x.Contract); - - // if not found, throw - if (viewController == null) - { - var message = $"Unable to resolve view for \"{x.ViewModel.GetType()}\""; - - if (x.Contract != null) - { - message += $" and contract \"{x.Contract.GetType()}\""; - } - - message += "."; - throw new Exception(message); - } - - // set the VM on the controller and stash a copy of the added view - viewController.ViewModel = x.ViewModel; - viewLastAdded = ((NSViewController)viewController).View; - - // sanity check, view controllers are expect to have a view - if (viewLastAdded == null) - { - var message = $"No view associated with view controller {viewController.GetType()}."; - throw new Exception(message); - } - - if (AddAutoLayoutConstraintsToSubView) - { - // see https://developer.apple.com/library/ios/documentation/userexperience/conceptual/AutolayoutPG/AdoptingAutoLayout/AdoptingAutoLayout.html - viewLastAdded.TranslatesAutoresizingMaskIntoConstraints = false; - } - - targetView.AddSubview(viewLastAdded); - - if (AddAutoLayoutConstraintsToSubView) - { - // Add edge constraints so that subview trails changes in parent - AddEdgeConstraint(NSLayoutAttribute.Left, targetView, viewLastAdded); - AddEdgeConstraint(NSLayoutAttribute.Right, targetView, viewLastAdded); - AddEdgeConstraint(NSLayoutAttribute.Top, targetView, viewLastAdded); - AddEdgeConstraint(NSLayoutAttribute.Bottom, targetView, viewLastAdded); - } - }); - } - - private void AddEdgeConstraint(NSLayoutAttribute edge, NSView parentView, NSView subView) - { - var constraint = NSLayoutConstraint.Create(subView, edge, NSLayoutRelation.Equal, parentView, edge, 1, 0); - parentView.AddConstraint(constraint); - } - - private NSViewController _defaultContent; - - public NSViewController DefaultContent - { - get => _defaultContent; - set => this.RaiseAndSetIfChanged(ref _defaultContent, value); - } - - private IReactiveObject _viewModel; - - public IReactiveObject ViewModel - { - get => _viewModel; - set => this.RaiseAndSetIfChanged(ref _viewModel, value); - } - - private IObservable _viewContractObservable; - - public IObservable ViewContractObservable - { - get => _viewContractObservable; - set => this.RaiseAndSetIfChanged(ref _viewContractObservable, value); - } - - public IViewLocator ViewLocator { get; set; } -#pragma warning restore SA1600 // Elements should be documented } } diff --git a/src/ReactiveUI/Platforms/ios/UIKitCommandBinders.cs b/src/ReactiveUI/Platforms/ios/UIKitCommandBinders.cs index 2ec375e6..00ac8be8 100644 --- a/src/ReactiveUI/Platforms/ios/UIKitCommandBinders.cs +++ b/src/ReactiveUI/Platforms/ios/UIKitCommandBinders.cs @@ -14,11 +14,6 @@ namespace ReactiveUI /// public class UIKitCommandBinders : FlexibleCommandBinder { - /// - /// The UIKitCommandBinders instance. - /// - public static Lazy Instance = new Lazy(); - /// /// Initializes a new instance of the class. /// @@ -28,5 +23,10 @@ namespace ReactiveUI Register(typeof(UIRefreshControl), 10, (cmd, t, cp) => ForEvent(cmd, t, cp, "ValueChanged", typeof(UIRefreshControl).GetRuntimeProperty("Enabled"))); Register(typeof(UIBarButtonItem), 10, (cmd, t, cp) => ForEvent(cmd, t, cp, "Clicked", typeof(UIBarButtonItem).GetRuntimeProperty("Enabled"))); } + + /// + /// Gets the UIKitCommandBinders instance. + /// + public static Lazy Instance { get; } = new Lazy(); } } diff --git a/src/ReactiveUI/Platforms/ios/UIKitObservableForProperty.cs b/src/ReactiveUI/Platforms/ios/UIKitObservableForProperty.cs index ceb97bc7..57b45734 100644 --- a/src/ReactiveUI/Platforms/ios/UIKitObservableForProperty.cs +++ b/src/ReactiveUI/Platforms/ios/UIKitObservableForProperty.cs @@ -16,11 +16,6 @@ namespace ReactiveUI [Preserve] public class UIKitObservableForProperty : ObservableForPropertyBase { - /// - /// The UI Kit ObservableForProperty instance. - /// - public static Lazy Instance = new Lazy(); - /// /// Initializes a new instance of the class. /// @@ -40,5 +35,10 @@ namespace ReactiveUI // Warning: This will stomp the Control's delegate Register(typeof(UISearchBar), "Text", 30, (s, p) => ObservableFromEvent(s, p, "TextChanged")); } + + /// + /// Gets the UI Kit ObservableForProperty instance. + /// + public static Lazy Instance { get; } = new Lazy(); } } diff --git a/src/ReactiveUI/Platforms/mac/AppKitObservableForProperty.cs b/src/ReactiveUI/Platforms/mac/AppKitObservableForProperty.cs index cd179deb..17589790 100644 --- a/src/ReactiveUI/Platforms/mac/AppKitObservableForProperty.cs +++ b/src/ReactiveUI/Platforms/mac/AppKitObservableForProperty.cs @@ -16,11 +16,6 @@ namespace ReactiveUI [Preserve] public class AppKitObservableForProperty : ObservableForPropertyBase { - /// - /// The App Kit ObservableForProperty instance. - /// - public static Lazy Instance = new Lazy(); - /// /// Initializes a new instance of the class. /// @@ -35,5 +30,10 @@ namespace ReactiveUI Register(typeof(NSControl), "StringValue", 20, (s, p) => ObservableFromNotification(s, p, NSControl.TextDidChangeNotification)); Register(typeof(NSControl), "AttributedStringValue", 20, (s, p) => ObservableFromNotification(s, p, NSControl.TextDidChangeNotification)); } + + /// + /// Gets the App Kit ObservableForProperty instance. + /// + public static Lazy Instance { get; } = new Lazy(); } } diff --git a/src/ReactiveUI/Platforms/mac/AppKitAutoSuspendHelper.cs b/src/ReactiveUI/Platforms/mac/AutoSuspendHelper.cs similarity index 73% rename from src/ReactiveUI/Platforms/mac/AppKitAutoSuspendHelper.cs rename to src/ReactiveUI/Platforms/mac/AutoSuspendHelper.cs index f4dd9d23..fd323cf5 100644 --- a/src/ReactiveUI/Platforms/mac/AppKitAutoSuspendHelper.cs +++ b/src/ReactiveUI/Platforms/mac/AutoSuspendHelper.cs @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information. using System; +using System.Diagnostics.CodeAnalysis; using System.Reactive; using System.Reactive.Concurrency; using System.Reactive.Disposables; @@ -18,14 +19,18 @@ namespace ReactiveUI /// AutoSuspend-based App Delegate. To use AutoSuspend with iOS, change your /// AppDelegate to inherit from this class, then call: /// - /// Locator.Current.GetService.().SetupDefaultSuspendResume(); + /// Locator.Current.GetService.{ISuspensionHost}().SetupDefaultSuspendResume(); + /// + /// This will fetch your SuspensionHost. /// - public class AutoSuspendHelper : IEnableLogger + public class AutoSuspendHelper : IEnableLogger, IDisposable { private readonly Subject _shouldPersistState = new Subject(); private readonly Subject _isResuming = new Subject(); private readonly Subject _isUnpausing = new Subject(); + private bool _isDisposed; + /// /// Initializes a new instance of the class. /// @@ -71,6 +76,7 @@ namespace ReactiveUI /// Dids the finish launching. /// /// The notification. + [SuppressMessage("Redundancy", "CA1801: Redundant parameter", Justification = "Legacy interface")] public void DidFinishLaunching(NSNotification notification) { _isResuming.OnNext(Unit.Default); @@ -80,6 +86,7 @@ namespace ReactiveUI /// Dids the resign active. /// /// The notification. + [SuppressMessage("Redundancy", "CA1801: Redundant parameter", Justification = "Legacy interface")] public void DidResignActive(NSNotification notification) { _shouldPersistState.OnNext(Disposable.Empty); @@ -89,6 +96,7 @@ namespace ReactiveUI /// Dids the become active. /// /// The notification. + [SuppressMessage("Redundancy", "CA1801: Redundant parameter", Justification = "Legacy interface")] public void DidBecomeActive(NSNotification notification) { _isUnpausing.OnNext(Unit.Default); @@ -98,9 +106,37 @@ namespace ReactiveUI /// Dids the hide. /// /// The notification. + [SuppressMessage("Redundancy", "CA1801: Redundant parameter", Justification = "Legacy interface")] public void DidHide(NSNotification notification) { _shouldPersistState.OnNext(Disposable.Empty); } + + /// + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + /// + /// Disposes of resources inside the class. + /// + /// If we are disposing managed resources. + protected virtual void Dispose(bool isDisposing) + { + if (_isDisposed) + { + return; + } + + if (isDisposing) + { + _isResuming?.Dispose(); + _isUnpausing?.Dispose(); + } + + _isDisposed = true; + } } } diff --git a/src/ReactiveUI/Platforms/mac/ReactiveWindowController.cs b/src/ReactiveUI/Platforms/mac/ReactiveWindowController.cs index 8bceb804..320af52b 100644 --- a/src/ReactiveUI/Platforms/mac/ReactiveWindowController.cs +++ b/src/ReactiveUI/Platforms/mac/ReactiveWindowController.cs @@ -27,7 +27,6 @@ namespace ReactiveUI protected ReactiveWindowController(NSWindow window) : base(window) { - SetupRxObj(); } /// @@ -37,7 +36,6 @@ namespace ReactiveUI protected ReactiveWindowController(string windowNibName) : base(windowNibName) { - SetupRxObj(); } /// @@ -48,7 +46,6 @@ namespace ReactiveUI protected ReactiveWindowController(string windowNibName, NSObject owner) : base(windowNibName, owner) { - SetupRxObj(); } /// @@ -58,7 +55,6 @@ namespace ReactiveUI protected ReactiveWindowController(NSCoder coder) : base(coder) { - SetupRxObj(); } /// @@ -68,7 +64,6 @@ namespace ReactiveUI protected ReactiveWindowController(NSObjectFlag t) : base(t) { - SetupRxObj(); } /// @@ -78,7 +73,6 @@ namespace ReactiveUI protected ReactiveWindowController(IntPtr handle) : base(handle) { - SetupRxObj(); } /// @@ -86,7 +80,6 @@ namespace ReactiveUI /// protected ReactiveWindowController() { - SetupRxObj(); } /// @@ -95,15 +88,10 @@ namespace ReactiveUI /// public event PropertyChangedEventHandler PropertyChanged; - /// - /// Represents an Observable that fires *before* a property is about to - /// be changed. - /// + /// public IObservable> Changing => this.GetChangingObservable(); - /// - /// Represents an Observable that fires *after* a property has changed. - /// + /// public IObservable> Changed => this.GetChangedObservable(); /// @@ -160,9 +148,5 @@ namespace ReactiveUI _activated.OnNext(Unit.Default); } - - private void SetupRxObj() - { - } } } diff --git a/src/ReactiveUI/Platforms/tizen/EcoreMainloopScheduler.cs b/src/ReactiveUI/Platforms/tizen/EcoreMainloopScheduler.cs index 7cde30d1..f9483662 100644 --- a/src/ReactiveUI/Platforms/tizen/EcoreMainloopScheduler.cs +++ b/src/ReactiveUI/Platforms/tizen/EcoreMainloopScheduler.cs @@ -11,7 +11,7 @@ namespace ReactiveUI { internal class EcoreMainloopScheduler : IScheduler { - public static IScheduler MainThreadScheduler = new EcoreMainloopScheduler(); + public static IScheduler MainThreadScheduler { get; } = new EcoreMainloopScheduler(); public DateTimeOffset Now => DateTimeOffset.Now; diff --git a/src/ReactiveUI/Platforms/tvos/UIKitCommandBinders.cs b/src/ReactiveUI/Platforms/tvos/UIKitCommandBinders.cs index 670b73b8..d054b444 100644 --- a/src/ReactiveUI/Platforms/tvos/UIKitCommandBinders.cs +++ b/src/ReactiveUI/Platforms/tvos/UIKitCommandBinders.cs @@ -14,11 +14,6 @@ namespace ReactiveUI /// public class UIKitCommandBinders : FlexibleCommandBinder { - /// - /// The UIKitCommandBinders instance. - /// - public static Lazy Instance = new Lazy(); - /// /// Initializes a new instance of the class. /// @@ -27,5 +22,10 @@ namespace ReactiveUI Register(typeof(UIControl), 9, (cmd, t, cp) => ForTargetAction(cmd, t, cp, typeof(UIControl).GetRuntimeProperty("Enabled"))); Register(typeof(UIBarButtonItem), 10, (cmd, t, cp) => ForEvent(cmd, t, cp, "Clicked", typeof(UIBarButtonItem).GetRuntimeProperty("Enabled"))); } + + /// + /// Gets the UIKitCommandBinders instance. + /// + public static Lazy Instance { get; } = new Lazy(); } } diff --git a/src/ReactiveUI/Platforms/tvos/UIKitObservableForProperty.cs b/src/ReactiveUI/Platforms/tvos/UIKitObservableForProperty.cs index ffa6ac09..3ba63313 100644 --- a/src/ReactiveUI/Platforms/tvos/UIKitObservableForProperty.cs +++ b/src/ReactiveUI/Platforms/tvos/UIKitObservableForProperty.cs @@ -16,11 +16,6 @@ namespace ReactiveUI [Preserve] public class UIKitObservableForProperty : ObservableForPropertyBase { - /// - /// UI Kit ObservableForProperty instance. - /// - public static Lazy Instance = new Lazy(); - /// /// Initializes a new instance of the class. /// @@ -38,5 +33,10 @@ namespace ReactiveUI // Warning: This will stomp the Control's delegate Register(typeof(UISearchBar), "Text", 30, (s, p) => ObservableFromEvent(s, p, "TextChanged")); } + + /// + /// Gets the UI Kit ObservableForProperty instance. + /// + public static Lazy Instance { get; } = new Lazy(); } } diff --git a/src/ReactiveUI/Platforms/uap10.0.16299/WinRTAutoSuspendApplication.cs b/src/ReactiveUI/Platforms/uap10.0.16299/AutoSuspendHelper.cs similarity index 75% rename from src/ReactiveUI/Platforms/uap10.0.16299/WinRTAutoSuspendApplication.cs rename to src/ReactiveUI/Platforms/uap10.0.16299/AutoSuspendHelper.cs index 1f63c794..a8fed7b4 100644 --- a/src/ReactiveUI/Platforms/uap10.0.16299/WinRTAutoSuspendApplication.cs +++ b/src/ReactiveUI/Platforms/uap10.0.16299/AutoSuspendHelper.cs @@ -23,10 +23,12 @@ namespace ReactiveUI /// Locator.Current.GetService.<ISuspensionHost>().SetupDefaultSuspendResume(); /// This will register your suspension host. /// - public class AutoSuspendHelper : IEnableLogger + public class AutoSuspendHelper : IEnableLogger, IDisposable { private readonly ReplaySubject _activated = new ReplaySubject(1); + private bool _isDisposed; + /// /// Initializes a new instance of the class. /// @@ -50,7 +52,7 @@ namespace ReactiveUI .Select(_ => Unit.Default); var shouldPersistState = new Subject(); - app.Suspending += (o, e) => shouldPersistState.OnNext(e); + app.Suspending += (_, e) => shouldPersistState.OnNext(e); RxApp.SuspensionHost.ShouldPersistState = shouldPersistState.Select(x => { @@ -59,17 +61,43 @@ namespace ReactiveUI }); var shouldInvalidateState = new Subject(); - app.UnhandledException += (o, e) => shouldInvalidateState.OnNext(Unit.Default); + app.UnhandledException += (_, __) => shouldInvalidateState.OnNext(Unit.Default); RxApp.SuspensionHost.ShouldInvalidateState = shouldInvalidateState; } /// - /// Raises the event. + /// Raises the applications Launch event. /// /// The instance containing the event data. public void OnLaunched(IActivatedEventArgs args) { _activated.OnNext(args); } + + /// + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + /// + /// Disposes of resources inside the class. + /// + /// If we are disposing managed resources. + protected virtual void Dispose(bool isDisposing) + { + if (_isDisposed) + { + return; + } + + if (isDisposing) + { + _activated?.Dispose(); + } + + _isDisposed = true; + } } } diff --git a/src/ReactiveUI/Platforms/uap10.0.16299/DependencyObjectObservableForProperty.cs b/src/ReactiveUI/Platforms/uap10.0.16299/DependencyObjectObservableForProperty.cs index 83eb0686..cd6ed90c 100644 --- a/src/ReactiveUI/Platforms/uap10.0.16299/DependencyObjectObservableForProperty.cs +++ b/src/ReactiveUI/Platforms/uap10.0.16299/DependencyObjectObservableForProperty.cs @@ -44,7 +44,8 @@ namespace ReactiveUI { this.Log().Warn( "Tried to bind DP on a non-DependencyObject. Binding as POCO object", - type.FullName, propertyName); + type.FullName, + propertyName); var ret = new POCOObservableForProperty(); return ret.GetNotificationForProperty(sender, expression, propertyName, beforeChanged); @@ -54,7 +55,8 @@ namespace ReactiveUI { this.Log().Warn( "Tried to bind DO {0}.{1}, but DPs can't do beforeChanged. Binding as POCO object", - type.FullName, propertyName); + type.FullName, + propertyName); var ret = new POCOObservableForProperty(); return ret.GetNotificationForProperty(sender, expression, propertyName, beforeChanged); @@ -65,7 +67,8 @@ namespace ReactiveUI { this.Log().Warn( "Tried to bind DO {0}.{1}, but DP doesn't exist. Binding as POCO object", - type.FullName, propertyName); + type.FullName, + propertyName); var ret = new POCOObservableForProperty(); return ret.GetNotificationForProperty(sender, expression, propertyName, beforeChanged); @@ -83,7 +86,41 @@ namespace ReactiveUI }); } - private Func GetDependencyPropertyFetcher(Type type, string propertyName) + private static PropertyInfo ActuallyGetProperty(TypeInfo typeInfo, string propertyName) + { + var current = typeInfo; + while (current != null) + { + var ret = current.GetDeclaredProperty(propertyName); + if (ret != null && ret.IsStatic()) + { + return ret; + } + + current = current.BaseType != null ? current.BaseType.GetTypeInfo() : null; + } + + return null; + } + + private static FieldInfo ActuallyGetField(TypeInfo typeInfo, string propertyName) + { + var current = typeInfo; + while (current != null) + { + var ret = current.GetDeclaredField(propertyName); + if (ret != null && ret.IsStatic) + { + return ret; + } + + current = current.BaseType != null ? current.BaseType.GetTypeInfo() : null; + } + + return null; + } + + private static Func GetDependencyPropertyFetcher(Type type, string propertyName) { var typeInfo = type.GetTypeInfo(); @@ -102,39 +139,5 @@ namespace ReactiveUI return null; } - - private PropertyInfo ActuallyGetProperty(TypeInfo typeInfo, string propertyName) - { - var current = typeInfo; - while (current != null) - { - var ret = current.GetDeclaredProperty(propertyName); - if (ret != null && ret.IsStatic()) - { - return ret; - } - - current = current.BaseType != null ? current.BaseType.GetTypeInfo() : null; - } - - return null; - } - - private FieldInfo ActuallyGetField(TypeInfo typeInfo, string propertyName) - { - var current = typeInfo; - while (current != null) - { - var ret = current.GetDeclaredField(propertyName); - if (ret != null && ret.IsStatic) - { - return ret; - } - - current = current.BaseType != null ? current.BaseType.GetTypeInfo() : null; - } - - return null; - } } } diff --git a/src/ReactiveUI/Platforms/uikit-common/AutoSuspendHelper.cs b/src/ReactiveUI/Platforms/uikit-common/AutoSuspendHelper.cs index 4f8f621d..ea8b7a43 100644 --- a/src/ReactiveUI/Platforms/uikit-common/AutoSuspendHelper.cs +++ b/src/ReactiveUI/Platforms/uikit-common/AutoSuspendHelper.cs @@ -20,14 +20,18 @@ namespace ReactiveUI /// AutoSuspend-based App Delegate. To use AutoSuspend with iOS, change your /// AppDelegate to inherit from this class, then call: /// - /// Locator.Current.GetService.().SetupDefaultSuspendResume(); + /// Locator.Current.GetService{ISuspensionHost}().SetupDefaultSuspendResume(); + /// + /// This will get your suspension host. /// - public class AutoSuspendHelper : IEnableLogger + public class AutoSuspendHelper : IEnableLogger, IDisposable { private readonly Subject _finishedLaunching = new Subject(); private readonly Subject _activated = new Subject(); private readonly Subject _backgrounded = new Subject(); + private bool _isDisposed; + /// /// Initializes a new instance of the class. /// @@ -112,5 +116,33 @@ namespace ReactiveUI { _backgrounded.OnNext(application); } + + /// + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + /// + /// Disposes of any disposable entities within the class. + /// + /// If we are going to call Dispose methods on field items. + protected virtual void Dispose(bool isDisposing) + { + if (_isDisposed) + { + return; + } + + if (isDisposing) + { + _activated?.Dispose(); + _backgrounded?.Dispose(); + _finishedLaunching?.Dispose(); + } + + _isDisposed = true; + } } } diff --git a/src/ReactiveUI/Platforms/uikit-common/CollectionViewSectionInformation.cs b/src/ReactiveUI/Platforms/uikit-common/CollectionViewSectionInformation.cs index 8b4a719d..af3000fa 100644 --- a/src/ReactiveUI/Platforms/uikit-common/CollectionViewSectionInformation.cs +++ b/src/ReactiveUI/Platforms/uikit-common/CollectionViewSectionInformation.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Specialized; +using System.Diagnostics.CodeAnalysis; using Foundation; using UIKit; @@ -10,6 +11,7 @@ namespace ReactiveUI /// and . /// /// The type of the source. + [SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:FileMayOnlyContainASingleType", Justification = "Classes with the same class names within.")] public class CollectionViewSectionInformation : ISectionInformation { /// @@ -28,6 +30,7 @@ namespace ReactiveUI /// /// The type of the source. /// The type of the UI collection view cell. + [SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:FileMayOnlyContainASingleType", Justification = "Classes with the same class names within.")] public class CollectionViewSectionInformation : CollectionViewSectionInformation where TCell : UICollectionViewCell { diff --git a/src/ReactiveUI/Platforms/uikit-common/CommonReactiveSource.cs b/src/ReactiveUI/Platforms/uikit-common/CommonReactiveSource.cs index 34294b54..d0a8d9bf 100644 --- a/src/ReactiveUI/Platforms/uikit-common/CommonReactiveSource.cs +++ b/src/ReactiveUI/Platforms/uikit-common/CommonReactiveSource.cs @@ -7,6 +7,7 @@ using System.Collections; using System.Collections.Generic; using System.Collections.Specialized; using System.Diagnostics; +using System.Globalization; using System.Linq; using System.Reactive; using System.Reactive.Concurrency; @@ -20,136 +21,7 @@ using Splat; namespace ReactiveUI { - /// - /// Interface used to extract a common API between - /// and . - /// - /// The ui view type. - /// The ui view call type. - internal interface IUICollViewAdapter - { - /// - /// Gets the is reloading data. - /// - IObservable IsReloadingData { get; } - - /// - /// Reloads the data. - /// - void ReloadData(); - - /// - /// Begins the updates. - /// - void BeginUpdates(); - - /// - /// Performs the updates. - /// - /// The updates. - /// The completion. - void PerformUpdates(Action updates, Action completion); - - /// - /// Ends the updates. - /// - void EndUpdates(); - - /// - /// Inserts the sections. - /// - /// The indexes. - void InsertSections(NSIndexSet indexes); - - /// - /// Deletes the sections. - /// - /// The indexes. - void DeleteSections(NSIndexSet indexes); - - /// - /// Reloads the sections. - /// - /// The indexes. - void ReloadSections(NSIndexSet indexes); - - /// - /// Moves the section. - /// - /// From index. - /// To index. - void MoveSection(int fromIndex, int toIndex); - - /// - /// Inserts the items. - /// - /// The paths. - void InsertItems(NSIndexPath[] paths); - - /// - /// Deletes the items. - /// - /// The paths. - void DeleteItems(NSIndexPath[] paths); - - /// - /// Reloads the items. - /// - /// The paths. - void ReloadItems(NSIndexPath[] paths); - - /// - /// Moves the item. - /// - /// The path. - /// The new path. - void MoveItem(NSIndexPath path, NSIndexPath newPath); - - /// - /// Dequeues the reusable cell. - /// - /// The cell key. - /// The path. - /// The ui view cell. - TUIViewCell DequeueReusableCell(NSString cellKey, NSIndexPath path); - } - - /// - /// Interface used to extract a common API between - /// and . - /// - /// The type of the source. - /// The type of the UI view. - /// The type of the UI view cell. - internal interface ISectionInformation - { - /// - /// Gets the collection. - /// - INotifyCollectionChanged Collection { get; } - - /// - /// Gets the cell key selector. - /// - Func CellKeySelector { get; } - - /// - /// Gets the initialize cell action. - /// - Action InitializeCellAction { get; } - } - - internal static class SectionInfoIdGenerator - { - private static int nextSectionInfoId; - - public static int Generate() - { - return nextSectionInfoId++; - } - } - - internal sealed class CommonReactiveSource : ReactiveObject, IDisposable, IEnableLogger + internal sealed class CommonReactiveSource : ReactiveObject, IDisposable where TSectionInfo : ISectionInformation { private readonly IUICollViewAdapter _adapter; @@ -160,6 +32,10 @@ namespace ReactiveUI private bool _isCollectingChanges; private IReadOnlyList _sectionInfo; + /// + /// Initializes a new instance of the class. + /// + /// The adapter to use which we want to display information for. public CommonReactiveSource(IUICollViewAdapter adapter) { _adapter = adapter; @@ -188,50 +64,50 @@ namespace ReactiveUI ex => this.Log().ErrorException("Error occurred when SectionInfo changed.", ex))); } - private bool IsDebugEnabled => this.Log().Level <= LogLevel.Debug; - public IReadOnlyList SectionInfo { get => _sectionInfo; set => this.RaiseAndSetIfChanged(ref _sectionInfo, value); } + private bool IsDebugEnabled => this.Log().Level <= LogLevel.Debug; + public int NumberOfSections() { - Debug.Assert(Thread.CurrentThread.ManagedThreadId == _mainThreadId); + Debug.Assert(Thread.CurrentThread.ManagedThreadId == _mainThreadId, "The thread is not the main thread."); var count = SectionInfo.Count; - this.Log().Debug("Reporting number of sections = {0}", count); + this.Log().Debug(CultureInfo.InvariantCulture, "Reporting number of sections = {0}", count); return count; } public int RowsInSection(int section) { - Debug.Assert(Thread.CurrentThread.ManagedThreadId == _mainThreadId); + Debug.Assert(Thread.CurrentThread.ManagedThreadId == _mainThreadId, "The thread is not the main thread."); var list = (IList)SectionInfo[section].Collection; var count = list.Count; - this.Log().Debug("Reporting rows in section {0} = {1}", section, count); + this.Log().Debug(CultureInfo.InvariantCulture, "Reporting rows in section {0} = {1}", section, count); return count; } public object ItemAt(NSIndexPath path) { - Debug.Assert(Thread.CurrentThread.ManagedThreadId == _mainThreadId); + Debug.Assert(Thread.CurrentThread.ManagedThreadId == _mainThreadId, "The thread is not the main thread."); var list = (IList)SectionInfo[path.Section].Collection; - this.Log().Debug("Returning item at {0}-{1}", path.Section, path.Row); + this.Log().Debug(CultureInfo.InvariantCulture, "Returning item at {0}-{1}", path.Section, path.Row); return list[path.Row]; } public TUIViewCell GetCell(NSIndexPath indexPath) { - Debug.Assert(Thread.CurrentThread.ManagedThreadId == _mainThreadId); + Debug.Assert(Thread.CurrentThread.ManagedThreadId == _mainThreadId, "The thread is not the main thread."); - this.Log().Debug("Getting cell for index path {0}-{1}", indexPath.Section, indexPath.Row); + this.Log().Debug(CultureInfo.InvariantCulture, "Getting cell for index path {0}-{1}", indexPath.Section, indexPath.Row); var section = SectionInfo[indexPath.Section]; var vm = ((IList)section.Collection)[indexPath.Row]; var cell = _adapter.DequeueReusableCell(section.CellKeySelector(vm), indexPath); @@ -239,7 +115,7 @@ namespace ReactiveUI if (view != null) { - this.Log().Debug("Setting VM for index path {0}-{1}", indexPath.Section, indexPath.Row); + this.Log().Debug(CultureInfo.InvariantCulture, "Setting VM for index path {0}-{1}", indexPath.Section, indexPath.Row); view.ViewModel = vm; } @@ -254,248 +130,6 @@ namespace ReactiveUI _mainDisposables.Dispose(); } - private void SectionInfoChanging() - { - VerifyOnMainThread(); - - this.Log().Debug("SectionInfo about to change, disposing of any subscriptions for previous SectionInfo."); - _sectionInfoDisposable.Disposable = null; - } - - private void SectionInfoChanged(IReadOnlyList sectionInfo) - { - VerifyOnMainThread(); - - // this ID just makes it possible to correlate log messages with a specific SectionInfo - var sectionInfoId = SectionInfoIdGenerator.Generate(); - this.Log().Debug("[#{0}] SectionInfo changed to {1}.", sectionInfoId, sectionInfo); - - if (sectionInfo == null) - { - _sectionInfoDisposable.Disposable = null; - return; - } - - var notifyCollectionChanged = sectionInfo as INotifyCollectionChanged; - - if (notifyCollectionChanged == null) - { - this.Log().Warn("[#{0}] SectionInfo {1} does not implement INotifyCollectionChanged - any added or removed sections will not be reflected in the UI.", sectionInfoId, sectionInfo); - } - - var sectionChanged = notifyCollectionChanged == null ? - Observable.Never : - notifyCollectionChanged.ObserveCollectionChanges().Select(_ => Unit.Default); - - var disposables = new CompositeDisposable(); - disposables.Add(Disposable.Create(() => this.Log().Debug("[#{0}] Disposed of section info", sectionInfoId))); - _sectionInfoDisposable.Disposable = disposables; - SubscribeToSectionInfoChanges(sectionInfoId, sectionInfo, sectionChanged, disposables); - } - - private void SubscribeToSectionInfoChanges(int sectionInfoId, IReadOnlyList sectionInfo, IObservable sectionChanged, CompositeDisposable disposables) - { - // holds a single disposable representing the monitoring of sectionInfo. - // once disposed, any changes to sectionInfo will no longer trigger any of the logic below - var sectionInfoDisposable = new SerialDisposable(); - disposables.Add(sectionInfoDisposable); - - disposables.Add( - sectionChanged.Subscribe(x => - { - VerifyOnMainThread(); - - this.Log().Debug("[#{0}] Calling ReloadData()", sectionInfoId); - _adapter.ReloadData(); - - // holds all the disposables created to monitor stuff inside the section - var sectionDisposables = new CompositeDisposable(); - sectionInfoDisposable.Disposable = sectionDisposables; - - // holds a single disposable for any outstanding request to apply pending changes - var applyPendingChangesDisposable = new SerialDisposable(); - sectionDisposables.Add(applyPendingChangesDisposable); - - var isReloading = _adapter - .IsReloadingData - .DistinctUntilChanged() - .Do(y => this.Log().Debug("[#{0}] IsReloadingData = {1}", sectionInfoId, y)) - .Publish(); - - var anySectionChanged = Observable - .Merge( - sectionInfo - .Select((y, index) => y.Collection.ObserveCollectionChanges().Select(z => new { Section = index, Change = z }))) - .Publish(); - - // since reloads are applied asynchronously, it is possible for data to change whilst the reload is occuring - // thus, we need to ensure any such changes result in another reload - sectionDisposables.Add( - isReloading - .Where(y => y) - .Join( - anySectionChanged, - _ => isReloading, - _ => Observable.Empty, - (_, __) => Unit.Default) - .Subscribe(_ => - { - VerifyOnMainThread(); - this.Log().Debug("[#{0}] A section changed whilst a reload is in progress - forcing another reload.", sectionInfoId); - - _adapter.ReloadData(); - _pendingChanges.Clear(); - _isCollectingChanges = false; - })); - - sectionDisposables.Add( - isReloading - .Where(y => !y) - .Join( - anySectionChanged, - _ => isReloading, - _ => Observable.Empty, - (reloading, changeDetails) => new { Change = changeDetails.Change, Section = changeDetails.Section }) - .Subscribe( - y => - { - VerifyOnMainThread(); - - if (IsDebugEnabled) - { - this.Log().Debug( - "[#{0}] Change detected in section {1} : Action = {2}, OldStartingIndex = {3}, NewStartingIndex = {4}, OldItems.Count = {5}, NewItems.Count = {6}", - sectionInfoId, - y.Section, - y.Change.EventArgs.Action, - y.Change.EventArgs.OldStartingIndex, - y.Change.EventArgs.NewStartingIndex, - y.Change.EventArgs.OldItems == null ? "null" : y.Change.EventArgs.OldItems.Count.ToString(), - y.Change.EventArgs.NewItems == null ? "null" : y.Change.EventArgs.NewItems.Count.ToString()); - } - - if (!_isCollectingChanges) - { - this.Log().Debug("[#{0}] A section changed whilst no reload is in progress - instigating collection of updates for later application.", sectionInfoId); - _isCollectingChanges = true; - - // immediately indicate to the view that there are changes underway, even though we don't apply them immediately - // this ensures that if application code itself calls BeginUpdates/EndUpdates on the view before the changes have been applied, those inconsistencies - // between what's in the data source versus what the view believes is in the data source won't trigger any errors because of the outstanding - // BeginUpdates call (calls to BeginUpdates/EndUpdates can be nested) - this.Log().Debug("[#{0}] BeginUpdates", sectionInfoId); - _adapter.BeginUpdates(); - - applyPendingChangesDisposable.Disposable = RxApp.MainThreadScheduler.Schedule( - () => - { - ApplyPendingChanges(sectionInfoId); - this.Log().Debug("[#{0}] EndUpdates", sectionInfoId); - _adapter.EndUpdates(); - _isCollectingChanges = false; - applyPendingChangesDisposable.Disposable = null; - }); - } - - _pendingChanges.Add(Tuple.Create(y.Section, new PendingChange(y.Change.EventArgs))); - }, - ex => this.Log().Error("[#{0}] Error while watching section collection: {1}", sectionInfoId, ex))); - - sectionDisposables.Add(isReloading.Connect()); - sectionDisposables.Add(anySectionChanged.Connect()); - })); - } - - private void ApplyPendingChanges(int sectionInfoId) - { - Debug.Assert(Thread.CurrentThread.ManagedThreadId == _mainThreadId); - Debug.Assert(_isCollectingChanges); - this.Log().Debug("[#{0}] Applying pending changes", sectionInfoId); - - try - { - _adapter.PerformUpdates( - () => - { - if (IsDebugEnabled) - { - this.Log().Debug("[#{0}] The pending changes (in order received) are:", sectionInfoId); - - foreach (var pendingChange in _pendingChanges) - { - this.Log().Debug( - "[#{0}] Section {1}: Action = {2}, OldStartingIndex = {3}, NewStartingIndex = {4}, OldItems.Count = {5}, NewItems.Count = {6}", - sectionInfoId, - pendingChange.Item1, - pendingChange.Item2.Action, - pendingChange.Item2.OldStartingIndex, - pendingChange.Item2.NewStartingIndex, - pendingChange.Item2.OldItems == null ? "null" : pendingChange.Item2.OldItems.Count.ToString(), - pendingChange.Item2.NewItems == null ? "null" : pendingChange.Item2.NewItems.Count.ToString()); - } - } - - foreach (var sectionedUpdates in _pendingChanges.GroupBy(x => x.Item1)) - { - var section = sectionedUpdates.First().Item1; - - this.Log().Debug("[#{0}] Processing updates for section {1}", sectionInfoId, section); - - var allSectionChanges = sectionedUpdates - .Select(x => x.Item2) - .ToList(); - - if (allSectionChanges.Any(x => x.Action == NotifyCollectionChangedAction.Reset)) - { - this.Log().Debug("[#{0}] Section {1} included a reset notification, so reloading that section.", sectionInfoId, section); - _adapter.ReloadSections(new NSIndexSet((nuint)section)); - continue; - } - - var updates = allSectionChanges - .SelectMany(GetUpdatesForEvent) - .ToList(); - var normalizedUpdates = IndexNormalizer.Normalize(updates); - - if (IsDebugEnabled) - { - this.Log().Debug( - "[#{0}] Updates for section {1}: {2}", - sectionInfoId, - section, - string.Join(":", updates)); - - this.Log().Debug( - "[#{0}] Normalized updates for section {1}: {2}", - sectionInfoId, - section, - string.Join(":", normalizedUpdates)); - } - - foreach (var normalizedUpdate in normalizedUpdates) - { - switch (normalizedUpdate.Type) - { - case UpdateType.Add: - DoUpdate(_adapter.InsertItems, new[] { normalizedUpdate.Index }, section); - break; - case UpdateType.Delete: - DoUpdate(_adapter.DeleteItems, new[] { normalizedUpdate.Index }, section); - break; - default: - throw new NotSupportedException(); - } - } - } - }, - () => this.Log().Debug("[#{0}] Pending changes applied", sectionInfoId)); - } - finally - { - _pendingChanges.Clear(); - } - } - private static IEnumerable GetUpdatesForEvent(PendingChange pendingChange) { switch (pendingChange.Action) @@ -529,6 +163,252 @@ namespace ReactiveUI } } + private void SectionInfoChanging() + { + VerifyOnMainThread(); + + this.Log().Debug(CultureInfo.InvariantCulture, "SectionInfo about to change, disposing of any subscriptions for previous SectionInfo."); + _sectionInfoDisposable.Disposable = null; + } + + private void SectionInfoChanged(IReadOnlyList sectionInfo) + { + VerifyOnMainThread(); + + // this ID just makes it possible to correlate log messages with a specific SectionInfo + var sectionInfoId = SectionInfoIdGenerator.Generate(); + this.Log().Debug(CultureInfo.InvariantCulture, "[#{0}] SectionInfo changed to {1}.", sectionInfoId, sectionInfo); + + if (sectionInfo == null) + { + _sectionInfoDisposable.Disposable = null; + return; + } + + var notifyCollectionChanged = sectionInfo as INotifyCollectionChanged; + + if (notifyCollectionChanged == null) + { + this.Log().Warn(CultureInfo.InvariantCulture, "[#{0}] SectionInfo {1} does not implement INotifyCollectionChanged - any added or removed sections will not be reflected in the UI.", sectionInfoId, sectionInfo); + } + + var sectionChanged = notifyCollectionChanged == null ? + Observable.Never : + notifyCollectionChanged.ObserveCollectionChanges().Select(_ => Unit.Default); + + var disposables = new CompositeDisposable(); + disposables.Add(Disposable.Create(() => this.Log().Debug(CultureInfo.InvariantCulture, "[#{0}] Disposed of section info", sectionInfoId))); + _sectionInfoDisposable.Disposable = disposables; + SubscribeToSectionInfoChanges(sectionInfoId, sectionInfo, sectionChanged, disposables); + } + + private void SubscribeToSectionInfoChanges(int sectionInfoId, IReadOnlyList sectionInfo, IObservable sectionChanged, CompositeDisposable disposables) + { + // holds a single disposable representing the monitoring of sectionInfo. + // once disposed, any changes to sectionInfo will no longer trigger any of the logic below + var sectionInfoDisposable = new SerialDisposable(); + disposables.Add(sectionInfoDisposable); + + disposables.Add( + sectionChanged.Subscribe(x => + { + VerifyOnMainThread(); + + this.Log().Debug(CultureInfo.InvariantCulture, "[#{0}] Calling ReloadData()", sectionInfoId); + _adapter.ReloadData(); + + // holds all the disposables created to monitor stuff inside the section + var sectionDisposables = new CompositeDisposable(); + sectionInfoDisposable.Disposable = sectionDisposables; + + // holds a single disposable for any outstanding request to apply pending changes + var applyPendingChangesDisposable = new SerialDisposable(); + sectionDisposables.Add(applyPendingChangesDisposable); + + var isReloading = _adapter + .IsReloadingData + .DistinctUntilChanged() + .Do(y => this.Log().Debug(CultureInfo.InvariantCulture, "[#{0}] IsReloadingData = {1}", sectionInfoId, y)) + .Publish(); + + var anySectionChanged = Observable + .Merge( + sectionInfo + .Select((y, index) => y.Collection.ObserveCollectionChanges().Select(z => new { Section = index, Change = z }))) + .Publish(); + + // since reloads are applied asynchronously, it is possible for data to change whilst the reload is occuring + // thus, we need to ensure any such changes result in another reload + sectionDisposables.Add( + isReloading + .Where(y => y) + .Join( + anySectionChanged, + _ => isReloading, + _ => Observable.Empty, + (_, __) => Unit.Default) + .Subscribe(_ => + { + VerifyOnMainThread(); + this.Log().Debug(CultureInfo.InvariantCulture, "[#{0}] A section changed whilst a reload is in progress - forcing another reload.", sectionInfoId); + + _adapter.ReloadData(); + _pendingChanges.Clear(); + _isCollectingChanges = false; + })); + + sectionDisposables.Add( + isReloading + .Where(y => !y) + .Join( + anySectionChanged, + _ => isReloading, + _ => Observable.Empty, + (reloading, changeDetails) => new { Change = changeDetails.Change, Section = changeDetails.Section }) + .Subscribe( + y => + { + VerifyOnMainThread(); + + if (IsDebugEnabled) + { + this.Log().Debug( + CultureInfo.InvariantCulture, + "[#{0}] Change detected in section {1} : Action = {2}, OldStartingIndex = {3}, NewStartingIndex = {4}, OldItems.Count = {5}, NewItems.Count = {6}", + sectionInfoId, + y.Section, + y.Change.EventArgs.Action, + y.Change.EventArgs.OldStartingIndex, + y.Change.EventArgs.NewStartingIndex, + y.Change.EventArgs.OldItems == null ? "null" : y.Change.EventArgs.OldItems.Count.ToString(CultureInfo.InvariantCulture), + y.Change.EventArgs.NewItems == null ? "null" : y.Change.EventArgs.NewItems.Count.ToString(CultureInfo.InvariantCulture)); + } + + if (!_isCollectingChanges) + { + this.Log().Debug(CultureInfo.InvariantCulture, "[#{0}] A section changed whilst no reload is in progress - instigating collection of updates for later application.", sectionInfoId); + _isCollectingChanges = true; + + // immediately indicate to the view that there are changes underway, even though we don't apply them immediately + // this ensures that if application code itself calls BeginUpdates/EndUpdates on the view before the changes have been applied, those inconsistencies + // between what's in the data source versus what the view believes is in the data source won't trigger any errors because of the outstanding + // BeginUpdates call (calls to BeginUpdates/EndUpdates can be nested) + this.Log().Debug("[#{0}] BeginUpdates", sectionInfoId); + _adapter.BeginUpdates(); + + applyPendingChangesDisposable.Disposable = RxApp.MainThreadScheduler.Schedule( + () => + { + ApplyPendingChanges(sectionInfoId); + this.Log().Debug(CultureInfo.InvariantCulture, "[#{0}] EndUpdates", sectionInfoId); + _adapter.EndUpdates(); + _isCollectingChanges = false; + applyPendingChangesDisposable.Disposable = null; + }); + } + + _pendingChanges.Add(Tuple.Create(y.Section, new PendingChange(y.Change.EventArgs))); + }, + ex => this.Log().Error("[#{0}] Error while watching section collection: {1}", sectionInfoId, ex))); + + sectionDisposables.Add(isReloading.Connect()); + sectionDisposables.Add(anySectionChanged.Connect()); + })); + } + + private void ApplyPendingChanges(int sectionInfoId) + { + Debug.Assert(Thread.CurrentThread.ManagedThreadId == _mainThreadId, "The thread is not the main thread."); + Debug.Assert(_isCollectingChanges, "Currently there are no changes to collect"); + this.Log().Debug("[#{0}] Applying pending changes", sectionInfoId); + + try + { + _adapter.PerformUpdates( + () => + { + if (IsDebugEnabled) + { + this.Log().Debug("[#{0}] The pending changes (in order received) are:", sectionInfoId); + + foreach (var pendingChange in _pendingChanges) + { + this.Log().Debug( + CultureInfo.InvariantCulture, + "[#{0}] Section {1}: Action = {2}, OldStartingIndex = {3}, NewStartingIndex = {4}, OldItems.Count = {5}, NewItems.Count = {6}", + sectionInfoId, + pendingChange.Item1, + pendingChange.Item2.Action, + pendingChange.Item2.OldStartingIndex, + pendingChange.Item2.NewStartingIndex, + pendingChange.Item2.OldItems == null ? "null" : pendingChange.Item2.OldItems.Count.ToString(CultureInfo.InvariantCulture), + pendingChange.Item2.NewItems == null ? "null" : pendingChange.Item2.NewItems.Count.ToString(CultureInfo.InvariantCulture)); + } + } + + foreach (var sectionedUpdates in _pendingChanges.GroupBy(x => x.Item1)) + { + var section = sectionedUpdates.First().Item1; + + this.Log().Debug(CultureInfo.InvariantCulture, "[#{0}] Processing updates for section {1}", sectionInfoId, section); + + var allSectionChanges = sectionedUpdates + .Select(x => x.Item2) + .ToList(); + + if (allSectionChanges.Any(x => x.Action == NotifyCollectionChangedAction.Reset)) + { + this.Log().Debug("[#{0}] Section {1} included a reset notification, so reloading that section.", sectionInfoId, section); + _adapter.ReloadSections(new NSIndexSet((nuint)section)); + continue; + } + + var updates = allSectionChanges + .SelectMany(GetUpdatesForEvent) + .ToList(); + var normalizedUpdates = IndexNormalizer.Normalize(updates); + + if (IsDebugEnabled) + { + this.Log().Debug( + CultureInfo.InvariantCulture, + "[#{0}] Updates for section {1}: {2}", + sectionInfoId, + section, + string.Join(":", updates)); + + this.Log().Debug( + CultureInfo.InvariantCulture, + "[#{0}] Normalized updates for section {1}: {2}", + sectionInfoId, + section, + string.Join(":", normalizedUpdates)); + } + + foreach (var normalizedUpdate in normalizedUpdates) + { + switch (normalizedUpdate.Type) + { + case UpdateType.Add: + DoUpdate(_adapter.InsertItems, new[] { normalizedUpdate.Index }, section); + break; + case UpdateType.Delete: + DoUpdate(_adapter.DeleteItems, new[] { normalizedUpdate.Index }, section); + break; + default: + throw new NotSupportedException(); + } + } + } + }, + () => this.Log().Debug(CultureInfo.InvariantCulture, "[#{0}] Pending changes applied", sectionInfoId)); + } + finally + { + _pendingChanges.Clear(); + } + } + private void DoUpdate(Action method, IEnumerable update, int section) { var toChange = update @@ -538,6 +418,7 @@ namespace ReactiveUI if (IsDebugEnabled) { this.Log().Debug( + CultureInfo.InvariantCulture, "Calling {0}: [{1}]", method.Method.Name, string.Join(",", toChange.Select(x => x.Section + "-" + x.Row))); @@ -558,30 +439,24 @@ namespace ReactiveUI // storing NotifyCollectionChangeEventArgs doesn't always work because external code can mutate the instance before we get a chance to apply it private sealed class PendingChange { - private readonly NotifyCollectionChangedAction _action; - private readonly IList _oldItems; - private readonly IList _newItems; - private readonly int _oldStartingIndex; - private readonly int _newStartingIndex; - public PendingChange(NotifyCollectionChangedEventArgs ea) { - _action = ea.Action; - _oldItems = ea.OldItems == null ? null : ea.OldItems.Cast().ToList(); - _newItems = ea.NewItems == null ? null : ea.NewItems.Cast().ToList(); - _oldStartingIndex = ea.OldStartingIndex; - _newStartingIndex = ea.NewStartingIndex; + Action = ea.Action; + OldItems = ea.OldItems == null ? null : ea.OldItems.Cast().ToList(); + NewItems = ea.NewItems == null ? null : ea.NewItems.Cast().ToList(); + OldStartingIndex = ea.OldStartingIndex; + NewStartingIndex = ea.NewStartingIndex; } - public NotifyCollectionChangedAction Action => _action; + public NotifyCollectionChangedAction Action { get; } - public IList OldItems => _oldItems; + public IList OldItems { get; } - public IList NewItems => _newItems; + public IList NewItems { get; } - public int OldStartingIndex => _oldStartingIndex; + public int OldStartingIndex { get; } - public int NewStartingIndex => _newStartingIndex; + public int NewStartingIndex { get; } } } } diff --git a/src/ReactiveUI/Platforms/uikit-common/FlexibleCommandBinder.cs b/src/ReactiveUI/Platforms/uikit-common/FlexibleCommandBinder.cs index f394c5e5..ab22b621 100644 --- a/src/ReactiveUI/Platforms/uikit-common/FlexibleCommandBinder.cs +++ b/src/ReactiveUI/Platforms/uikit-common/FlexibleCommandBinder.cs @@ -16,7 +16,7 @@ namespace ReactiveUI /// /// Generic command binder platform registrations. /// - /// + /// public abstract class FlexibleCommandBinder : ICreatesCommandBinding { /// @@ -74,23 +74,6 @@ namespace ReactiveUI throw new NotImplementedException(); } - private class CommandBindingInfo - { - public int Affinity; - public Func, IDisposable> CreateBinding; - } - - /// - /// Registers an observable factory for the specified type and property. - /// - /// The type. - /// The affinity. - /// The create binding. - protected void Register(Type type, int affinity, Func, IDisposable> createBinding) - { - _config[type] = new CommandBindingInfo { Affinity = affinity, CreateBinding = createBinding }; - } - /// /// Creates a commands binding from event and a property. /// @@ -124,14 +107,12 @@ namespace ReactiveUI // initial enabled state enabledSetter(target, command.CanExecute(latestParam), null); - var compDisp = new CompositeDisposable( + return new CompositeDisposable( actionDisp, commandParameter.Subscribe(x => latestParam = x), Observable.FromEventPattern(x => command.CanExecuteChanged += x, x => command.CanExecuteChanged -= x) .Select(_ => command.CanExecute(latestParam)) .Subscribe(x => enabledSetter(target, x, null))); - - return compDisp; } /// @@ -174,14 +155,30 @@ namespace ReactiveUI // Initial enabled state enabledSetter(target, command.CanExecute(latestParam), null); - var compDisp = new CompositeDisposable( + return new CompositeDisposable( actionDisp, commandParameter.Subscribe(x => latestParam = x), Observable.FromEventPattern(x => command.CanExecuteChanged += x, x => command.CanExecuteChanged -= x) .Select(_ => command.CanExecute(latestParam)) .Subscribe(x => enabledSetter(target, x, null))); + } - return compDisp; + /// + /// Registers an observable factory for the specified type and property. + /// + /// The type. + /// The affinity. + /// The create binding. + protected void Register(Type type, int affinity, Func, IDisposable> createBinding) + { + _config[type] = new CommandBindingInfo { Affinity = affinity, CreateBinding = createBinding }; + } + + private class CommandBindingInfo + { + public int Affinity { get; set; } + + public Func, IDisposable> CreateBinding { get; set; } } } } diff --git a/src/ReactiveUI/Platforms/uikit-common/ISectionInformation.cs b/src/ReactiveUI/Platforms/uikit-common/ISectionInformation.cs new file mode 100644 index 00000000..1e5c8e22 --- /dev/null +++ b/src/ReactiveUI/Platforms/uikit-common/ISectionInformation.cs @@ -0,0 +1,35 @@ +// 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; +using System.Collections.Specialized; +using Foundation; + +namespace ReactiveUI +{ + /// + /// Interface used to extract a common API between + /// and . + /// + /// The type of the source. + /// The type of the UI view. + /// The type of the UI view cell. + internal interface ISectionInformation + { + /// + /// Gets the collection. + /// + INotifyCollectionChanged Collection { get; } + + /// + /// Gets the cell key selector. + /// + Func CellKeySelector { get; } + + /// + /// Gets the initialize cell action. + /// + Action InitializeCellAction { get; } + } +} diff --git a/src/ReactiveUI/Platforms/uikit-common/IUICollViewAdapter.cs b/src/ReactiveUI/Platforms/uikit-common/IUICollViewAdapter.cs new file mode 100644 index 00000000..39e1b5fb --- /dev/null +++ b/src/ReactiveUI/Platforms/uikit-common/IUICollViewAdapter.cs @@ -0,0 +1,103 @@ +// 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; +using Foundation; + +namespace ReactiveUI +{ + /// + /// Interface used to extract a common API between + /// and . + /// + /// The ui view type. + /// The ui view call type. + internal interface IUICollViewAdapter + { + /// + /// Gets the is reloading data. + /// + IObservable IsReloadingData { get; } + + /// + /// Reloads the data. + /// + void ReloadData(); + + /// + /// Begins the updates. + /// + void BeginUpdates(); + + /// + /// Performs the updates. + /// + /// The updates. + /// The completion. + void PerformUpdates(Action updates, Action completion); + + /// + /// Ends the updates. + /// + void EndUpdates(); + + /// + /// Inserts the sections. + /// + /// The indexes. + void InsertSections(NSIndexSet indexes); + + /// + /// Deletes the sections. + /// + /// The indexes. + void DeleteSections(NSIndexSet indexes); + + /// + /// Reloads the sections. + /// + /// The indexes. + void ReloadSections(NSIndexSet indexes); + + /// + /// Moves the section. + /// + /// From index. + /// To index. + void MoveSection(int fromIndex, int toIndex); + + /// + /// Inserts the items. + /// + /// The paths. + void InsertItems(NSIndexPath[] paths); + + /// + /// Deletes the items. + /// + /// The paths. + void DeleteItems(NSIndexPath[] paths); + + /// + /// Reloads the items. + /// + /// The paths. + void ReloadItems(NSIndexPath[] paths); + + /// + /// Moves the item. + /// + /// The path. + /// The new path. + void MoveItem(NSIndexPath path, NSIndexPath newPath); + + /// + /// Dequeues the reusable cell. + /// + /// The cell key. + /// The path. + /// The ui view cell. + TUIViewCell DequeueReusableCell(NSString cellKey, NSIndexPath path); + } +} diff --git a/src/ReactiveUI/Platforms/uikit-common/ReactiveCollectionReusableView.cs b/src/ReactiveUI/Platforms/uikit-common/ReactiveCollectionReusableView.cs index 637ee041..faf5a125 100644 --- a/src/ReactiveUI/Platforms/uikit-common/ReactiveCollectionReusableView.cs +++ b/src/ReactiveUI/Platforms/uikit-common/ReactiveCollectionReusableView.cs @@ -4,6 +4,7 @@ using System; using System.ComponentModel; +using System.Diagnostics.CodeAnalysis; using System.Reactive; using System.Reactive.Linq; using System.Reactive.Subjects; @@ -17,8 +18,9 @@ namespace ReactiveUI /// This is a UICollectionReusableView that is both an UICollectionReusableView and has ReactiveObject powers /// (i.e. you can call RaiseAndSetIfChanged). /// - public abstract class ReactiveCollectionReusableView : UICollectionReusableView, - IReactiveNotifyPropertyChanged, IHandleObservableErrors, IReactiveObject, ICanActivate + [SuppressMessage("Design", "CA1010: Implement generic IEnumerable", Justification = "UI Kit exposes IEnumerable")] + [SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:FileMayOnlyContainASingleType", Justification = "Classes with the same class names within.")] + public abstract class ReactiveCollectionReusableView : UICollectionReusableView, IReactiveNotifyPropertyChanged, IHandleObservableErrors, IReactiveObject, ICanActivate { private Subject _activated = new Subject(); private Subject _deactivated = new Subject(); @@ -30,7 +32,6 @@ namespace ReactiveUI protected ReactiveCollectionReusableView(CGRect frame) : base(frame) { - SetupRxObj(); } /// @@ -38,7 +39,6 @@ namespace ReactiveUI /// protected ReactiveCollectionReusableView() { - SetupRxObj(); } /// @@ -48,7 +48,6 @@ namespace ReactiveUI protected ReactiveCollectionReusableView(IntPtr handle) : base(handle) { - SetupRxObj(); } /// @@ -58,7 +57,6 @@ namespace ReactiveUI protected ReactiveCollectionReusableView(NSObjectFlag t) : base(t) { - SetupRxObj(); } /// @@ -68,7 +66,6 @@ namespace ReactiveUI protected ReactiveCollectionReusableView(NSCoder coder) : base(coder) { - SetupRxObj(); } /// @@ -77,15 +74,10 @@ namespace ReactiveUI /// public event PropertyChangedEventHandler PropertyChanged; - /// - /// Represents an Observable that fires *before* a property is about to - /// be changed. - /// + /// public IObservable> Changing => this.GetChangingObservable(); - /// - /// Represents an Observable that fires *after* a property has changed. - /// + /// public IObservable> Changed => this.GetChangedObservable(); /// @@ -142,10 +134,6 @@ namespace ReactiveUI base.RemoveFromSuperview(); _deactivated.OnNext(Unit.Default); } - - private void SetupRxObj() - { - } } /// @@ -153,6 +141,8 @@ namespace ReactiveUI /// (i.e. you can call RaiseAndSetIfChanged). /// /// The view model type. + [SuppressMessage("Design", "CA1010: Implement generic IEnumerable", Justification = "UI Kit exposes IEnumerable")] + [SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:FileMayOnlyContainASingleType", Justification = "Classes with the same class names within.")] public abstract class ReactiveCollectionReusableView : ReactiveCollectionReusableView, IViewFor where TViewModel : class { diff --git a/src/ReactiveUI/Platforms/uikit-common/ReactiveCollectionView.cs b/src/ReactiveUI/Platforms/uikit-common/ReactiveCollectionView.cs index e42fa516..7820f711 100644 --- a/src/ReactiveUI/Platforms/uikit-common/ReactiveCollectionView.cs +++ b/src/ReactiveUI/Platforms/uikit-common/ReactiveCollectionView.cs @@ -4,6 +4,7 @@ using System; using System.ComponentModel; +using System.Diagnostics.CodeAnalysis; using System.Reactive; using System.Reactive.Concurrency; using System.Reactive.Linq; @@ -18,8 +19,9 @@ namespace ReactiveUI /// This is a UICollectionView that is both an UICollectionView and has ReactiveObject powers /// (i.e. you can call RaiseAndSetIfChanged). /// - public abstract class ReactiveCollectionView : UICollectionView, - IReactiveNotifyPropertyChanged, IHandleObservableErrors, IReactiveObject, ICanActivate, ICanForceManualActivation + [SuppressMessage("Design", "CA1010: Implement generic IEnumerable", Justification = "UI Kit exposes IEnumerable")] + [SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:FileMayOnlyContainASingleType", Justification = "Classes with the same class names within.")] + public abstract class ReactiveCollectionView : UICollectionView, IReactiveNotifyPropertyChanged, IHandleObservableErrors, IReactiveObject, ICanActivate, ICanForceManualActivation { private Subject _activated = new Subject(); private Subject _deactivated = new Subject(); @@ -32,7 +34,6 @@ namespace ReactiveUI protected ReactiveCollectionView(CGRect frame, UICollectionViewLayout layout) : base(frame, layout) { - SetupRxObj(); } /// @@ -42,7 +43,6 @@ namespace ReactiveUI protected ReactiveCollectionView(IntPtr handle) : base(handle) { - SetupRxObj(); } /// @@ -52,7 +52,6 @@ namespace ReactiveUI protected ReactiveCollectionView(NSObjectFlag t) : base(t) { - SetupRxObj(); } /// @@ -62,7 +61,6 @@ namespace ReactiveUI protected ReactiveCollectionView(NSCoder coder) : base(coder) { - SetupRxObj(); } /// @@ -79,15 +77,10 @@ namespace ReactiveUI remove => PropertyChangedEventManager.RemoveHandler(this, value); } - /// - /// Represents an Observable that fires *before* a property is about to - /// be changed. - /// + /// public IObservable> Changing => this.GetChangingObservable(); - /// - /// Represents an Observable that fires *after* a property has changed. - /// + /// public IObservable> Changed => this.GetChangedObservable(); /// @@ -143,10 +136,6 @@ namespace ReactiveUI RxApp.MainThreadScheduler.Schedule(() => (activate ? _activated : _deactivated).OnNext(Unit.Default)); } - - private void SetupRxObj() - { - } } /// @@ -154,6 +143,8 @@ namespace ReactiveUI /// (i.e. you can call RaiseAndSetIfChanged). /// /// The view model type. + [SuppressMessage("Design", "CA1010: Implement generic IEnumerable", Justification = "UI Kit exposes IEnumerable")] + [SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:FileMayOnlyContainASingleType", Justification = "Classes with the same class names within.")] public abstract class ReactiveCollectionView : ReactiveCollectionView, IViewFor where TViewModel : class { diff --git a/src/ReactiveUI/Platforms/uikit-common/ReactiveCollectionViewCell.cs b/src/ReactiveUI/Platforms/uikit-common/ReactiveCollectionViewCell.cs index 0b4cc200..3d5ab2ba 100644 --- a/src/ReactiveUI/Platforms/uikit-common/ReactiveCollectionViewCell.cs +++ b/src/ReactiveUI/Platforms/uikit-common/ReactiveCollectionViewCell.cs @@ -4,6 +4,7 @@ using System; using System.ComponentModel; +using System.Diagnostics.CodeAnalysis; using System.Reactive; using System.Reactive.Concurrency; using System.Reactive.Linq; @@ -18,6 +19,8 @@ namespace ReactiveUI /// This is a UICollectionViewCell that is both an UICollectionViewCell and has ReactiveObject powers /// (i.e. you can call RaiseAndSetIfChanged). /// + [SuppressMessage("Design", "CA1010: Implement generic IEnumerable", Justification = "UI Kit exposes IEnumerable")] + [SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:FileMayOnlyContainASingleType", Justification = "Classes with the same class names within.")] public abstract class ReactiveCollectionViewCell : UICollectionViewCell, IReactiveNotifyPropertyChanged, IHandleObservableErrors, IReactiveObject, ICanActivate { private Subject _activated = new Subject(); @@ -30,7 +33,6 @@ namespace ReactiveUI protected ReactiveCollectionViewCell(CGRect frame) : base(frame) { - SetupRxObj(); } /// @@ -40,17 +42,16 @@ namespace ReactiveUI protected ReactiveCollectionViewCell(NSObjectFlag t) : base(t) { - SetupRxObj(); } /// /// Initializes a new instance of the class. /// /// The coder. + [SuppressMessage("Redundancy", "CA1801: Redundant parameter", Justification = "Legacy interface")] protected ReactiveCollectionViewCell(NSCoder coder) : base(NSObjectFlag.Empty) { - SetupRxObj(); } /// @@ -58,7 +59,6 @@ namespace ReactiveUI /// protected ReactiveCollectionViewCell() { - SetupRxObj(); } /// @@ -68,7 +68,6 @@ namespace ReactiveUI protected ReactiveCollectionViewCell(IntPtr handle) : base(handle) { - SetupRxObj(); } /// @@ -85,15 +84,10 @@ namespace ReactiveUI remove => PropertyChangedEventManager.RemoveHandler(this, value); } - /// - /// Represents an Observable that fires *before* a property is about to - /// be changed. - /// + /// public IObservable> Changing => this.GetChangingObservable(); - /// - /// Represents an Observable that fires *after* a property has changed. - /// + /// public IObservable> Changed => this.GetChangedObservable(); /// @@ -135,10 +129,6 @@ namespace ReactiveUI base.WillMoveToSuperview(newsuper); (newsuper != null ? _activated : _deactivated).OnNext(Unit.Default); } - - private void SetupRxObj() - { - } } /// @@ -146,6 +136,8 @@ namespace ReactiveUI /// (i.e. you can call RaiseAndSetIfChanged). /// /// The view model type. + [SuppressMessage("Design", "CA1010: Implement generic IEnumerable", Justification = "UI Kit exposes IEnumerable")] + [SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:FileMayOnlyContainASingleType", Justification = "Classes with the same class names within.")] public abstract class ReactiveCollectionViewCell : ReactiveCollectionViewCell, IViewFor where TViewModel : class { @@ -164,6 +156,7 @@ namespace ReactiveUI /// Initializes a new instance of the class. /// /// The coder. + [SuppressMessage("Redundancy", "CA1801: Redundant parameter", Justification = "Legacy interface")] protected ReactiveCollectionViewCell(NSCoder coder) : base(NSObjectFlag.Empty) { diff --git a/src/ReactiveUI/Platforms/uikit-common/ReactiveCollectionViewController.cs b/src/ReactiveUI/Platforms/uikit-common/ReactiveCollectionViewController.cs index f28e42f7..71a020b8 100644 --- a/src/ReactiveUI/Platforms/uikit-common/ReactiveCollectionViewController.cs +++ b/src/ReactiveUI/Platforms/uikit-common/ReactiveCollectionViewController.cs @@ -4,6 +4,7 @@ using System; using System.ComponentModel; +using System.Diagnostics.CodeAnalysis; using System.Reactive; using System.Reactive.Linq; using System.Reactive.Subjects; @@ -16,6 +17,8 @@ namespace ReactiveUI /// This is a UICollectionViewController that is both an UICollectionViewController and has ReactiveObject powers /// (i.e. you can call RaiseAndSetIfChanged). /// + [SuppressMessage("Design", "CA1010: Implement generic IEnumerable", Justification = "UI Kit exposes IEnumerable")] + [SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:FileMayOnlyContainASingleType", Justification = "Classes with the same class names within.")] public abstract class ReactiveCollectionViewController : UICollectionViewController, IReactiveNotifyPropertyChanged, IHandleObservableErrors, IReactiveObject, ICanActivate { @@ -29,7 +32,6 @@ namespace ReactiveUI protected ReactiveCollectionViewController(UICollectionViewLayout withLayout) : base(withLayout) { - SetupRxObj(); } /// @@ -40,7 +42,6 @@ namespace ReactiveUI protected ReactiveCollectionViewController(string nibName, NSBundle bundle) : base(nibName, bundle) { - SetupRxObj(); } /// @@ -50,7 +51,6 @@ namespace ReactiveUI protected ReactiveCollectionViewController(IntPtr handle) : base(handle) { - SetupRxObj(); } /// @@ -60,7 +60,6 @@ namespace ReactiveUI protected ReactiveCollectionViewController(NSObjectFlag t) : base(t) { - SetupRxObj(); } /// @@ -70,7 +69,6 @@ namespace ReactiveUI protected ReactiveCollectionViewController(NSCoder coder) : base(coder) { - SetupRxObj(); } /// @@ -78,7 +76,6 @@ namespace ReactiveUI /// protected ReactiveCollectionViewController() { - SetupRxObj(); } /// @@ -95,15 +92,10 @@ namespace ReactiveUI remove => PropertyChangedEventManager.RemoveHandler(this, value); } - /// - /// Represents an Observable that fires *before* a property is about to - /// be changed. - /// + /// public IObservable> Changing => this.GetChangingObservable(); - /// - /// Represents an Observable that fires *after* a property has changed. - /// + /// public IObservable> Changed => this.GetChangedObservable(); /// @@ -154,10 +146,6 @@ namespace ReactiveUI _deactivated.OnNext(Unit.Default); this.ActivateSubviews(false); } - - private void SetupRxObj() - { - } } /// @@ -165,6 +153,8 @@ namespace ReactiveUI /// (i.e. you can call RaiseAndSetIfChanged). /// /// The view model type. + [SuppressMessage("Design", "CA1010: Implement generic IEnumerable", Justification = "UI Kit exposes IEnumerable")] + [SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:FileMayOnlyContainASingleType", Justification = "Classes with the same class names within.")] public abstract class ReactiveCollectionViewController : ReactiveCollectionViewController, IViewFor where TViewModel : class { diff --git a/src/ReactiveUI/Platforms/uikit-common/ReactiveCollectionViewSource.cs b/src/ReactiveUI/Platforms/uikit-common/ReactiveCollectionViewSource.cs index 0ddcc952..86327987 100644 --- a/src/ReactiveUI/Platforms/uikit-common/ReactiveCollectionViewSource.cs +++ b/src/ReactiveUI/Platforms/uikit-common/ReactiveCollectionViewSource.cs @@ -6,126 +6,14 @@ using System; using System.Collections.Generic; using System.Collections.Specialized; using System.ComponentModel; -using System.Diagnostics; -using System.Linq; -using System.Reactive.Concurrency; -using System.Reactive.Disposables; -using System.Reactive.Linq; using System.Reactive.Subjects; using Foundation; using ReactiveUI.Legacy; using Splat; using UIKit; -using NSAction = System.Action; namespace ReactiveUI { - internal class UICollectionViewAdapter : IUICollViewAdapter - { - private readonly UICollectionView _view; - private readonly BehaviorSubject _isReloadingData; - private int _inFlightReloads; - - internal UICollectionViewAdapter(UICollectionView view) - { - _view = view; - _isReloadingData = new BehaviorSubject(false); - } - - public IObservable IsReloadingData => _isReloadingData.AsObservable(); - - public void ReloadData() - { - ++_inFlightReloads; - _view.ReloadData(); - - if (_inFlightReloads == 1) - { - Debug.Assert(!_isReloadingData.Value); - _isReloadingData.OnNext(true); - } - - // since ReloadData() queues the appropriate messages on the UI thread, we know we're done reloading - // when this subsequent message is processed (with one caveat - see FinishReloadData for details) - RxApp.MainThreadScheduler.Schedule(FinishReloadData); - } - - // UICollectionView no longer has these methods so these are no-ops - public void BeginUpdates() - { - } - - public void EndUpdates() - { - } - - public void PerformUpdates(Action updates, Action completion) - { - _view.PerformBatchUpdates(new NSAction(updates), (completed) => completion()); - } - - public void InsertSections(NSIndexSet indexes) - { - _view.InsertSections(indexes); - } - - public void DeleteSections(NSIndexSet indexes) - { - _view.DeleteSections(indexes); - } - - public void ReloadSections(NSIndexSet indexes) - { - _view.ReloadSections(indexes); - } - - public void MoveSection(int fromIndex, int toIndex) - { - _view.MoveSection(fromIndex, toIndex); - } - - public void InsertItems(NSIndexPath[] paths) - { - _view.InsertItems(paths); - } - - public void DeleteItems(NSIndexPath[] paths) - { - _view.DeleteItems(paths); - } - - public void ReloadItems(NSIndexPath[] paths) - { - _view.ReloadItems(paths); - } - - public void MoveItem(NSIndexPath path, NSIndexPath newPath) - { - _view.MoveItem(path, newPath); - } - - public UICollectionViewCell DequeueReusableCell(NSString cellKey, NSIndexPath path) - { - return (UICollectionViewCell)_view.DequeueReusableCell(cellKey, path); - } - - private void FinishReloadData() - { - --_inFlightReloads; - - if (_inFlightReloads == 0) - { - // this is required because sometimes iOS schedules further work that results in calls to GetCell - // that work could happen after FinishReloadData unless we force layout here - // of course, we can't have that work running after IsReloading ticks to false because otherwise - // some updates may occur before the calls to GetCell and thus the calls to GetCell could fail due to invalid indexes - _view.LayoutIfNeeded(); - Debug.Assert(_isReloadingData.Value); - _isReloadingData.OnNext(false); - } - } - } - /// /// ReactiveCollectionViewSource is a Collection View Source that is /// connected to a Read Only List that automatically updates the View based @@ -133,7 +21,7 @@ namespace ReactiveUI /// View items are animated in and out as items are added. /// /// The source type. - public class ReactiveCollectionViewSource : UICollectionViewSource, IEnableLogger, IDisposable, IReactiveNotifyPropertyChanged>, IHandleObservableErrors, IReactiveObject + public class ReactiveCollectionViewSource : UICollectionViewSource, IEnableLogger, IReactiveNotifyPropertyChanged>, IHandleObservableErrors, IReactiveObject { private readonly CommonReactiveSource> _commonSource; private readonly Subject _elementSelected = new Subject(); @@ -169,14 +57,27 @@ namespace ReactiveUI /// The ui collection view. public ReactiveCollectionViewSource(UICollectionView collectionView) { - SetupRxObj(); var adapter = new UICollectionViewAdapter(collectionView); _commonSource = new CommonReactiveSource>(adapter); } + /// + public event PropertyChangingEventHandler PropertyChanging + { + add => PropertyChangingEventManager.AddHandler(this, value); + remove => PropertyChangingEventManager.RemoveHandler(this, value); + } + + /// + public event PropertyChangedEventHandler PropertyChanged + { + add => PropertyChangedEventManager.AddHandler(this, value); + remove => PropertyChangedEventManager.RemoveHandler(this, value); + } + /// /// Gets or sets the data that should be displayed by this - /// . You should + /// . You should /// probably bind your view model to this property. /// If the list implements , /// then the source will react to changes to the contents of the list as well. @@ -203,6 +104,20 @@ namespace ReactiveUI /// public IObservable ElementSelected => _elementSelected; + /// + /// Gets an Observable that signals *before* a property is about to + /// be changed. + /// + public IObservable>> Changing => this.GetChangingObservable(); + + /// + /// Gets an an Observable that signals *after* a property has changed. + /// + public IObservable>> Changed => this.GetChangedObservable(); + + /// + public IObservable ThrownExceptions => this.GetThrownExceptionsObservable(); + /// public override UICollectionViewCell GetCell(UICollectionView collectionView, NSIndexPath indexPath) { @@ -237,61 +152,18 @@ namespace ReactiveUI return _commonSource.ItemAt(indexPath); } - /// - protected override void Dispose(bool disposing) - { - if (disposing) - { - _commonSource.Dispose(); - } - - base.Dispose(disposing); - } - - /// - public event PropertyChangingEventHandler PropertyChanging - { - add => PropertyChangingEventManager.AddHandler(this, value); - remove => PropertyChangingEventManager.RemoveHandler(this, value); - } - /// void IReactiveObject.RaisePropertyChanging(PropertyChangingEventArgs args) { PropertyChangingEventManager.DeliverEvent(this, args); } - /// - public event PropertyChangedEventHandler PropertyChanged - { - add => PropertyChangedEventManager.AddHandler(this, value); - remove => PropertyChangedEventManager.RemoveHandler(this, value); - } - /// void IReactiveObject.RaisePropertyChanged(PropertyChangedEventArgs args) { PropertyChangedEventManager.DeliverEvent(this, args); } - /// - /// Represents an Observable that fires *before* a property is about to - /// be changed. - /// - public IObservable>> Changing => this.GetChangingObservable(); - - /// - /// Represents an Observable that fires *after* a property has changed. - /// - public IObservable>> Changed => this.GetChangedObservable(); - - /// - public IObservable ThrownExceptions => this.GetThrownExceptionsObservable(); - - private void SetupRxObj() - { - } - /// /// When this method is called, an object will not fire change /// notifications (neither traditional nor Observable notifications) @@ -303,104 +175,16 @@ namespace ReactiveUI { return IReactiveObjectExtensions.SuppressChangeNotifications(this); } - } - /// - /// Extension methods for . - /// - public static class ReactiveCollectionViewSourceExtensions - { - /// - /// Extension method that binds an observable of a list of collection - /// sections as the source of a . - /// If your is also an instance of - /// , then this method - /// will silently update the bindings whenever it changes as well. - /// Otherwise, it will just log a message. - /// - /// The used to dispose this binding. - /// Sections observable. - /// Collection view. - /// Optionally initializes some property of - /// the . - /// Type of the view source. - /// Type of the . - public static IDisposable BindTo( - this IObservable>> sectionsObservable, - UICollectionView collectionView, - Func, IDisposable> initSource = null) - where TCell : UICollectionViewCell + /// + protected override void Dispose(bool disposing) { - var source = new ReactiveCollectionViewSource(collectionView); - if (initSource != null) + if (disposing) { - initSource(source); + _commonSource.Dispose(); } - var bind = sectionsObservable.BindTo(source, x => x.Data); - collectionView.Source = source; - return new CompositeDisposable(bind, source); - } - - /// - /// Extension method that binds an observable of a collection - /// as the source of a . - /// - /// The used to dispose this binding. - /// Source collection observable. - /// Collection view. - /// Cell key. - /// Initialize cell action. - /// Optionally initializes some property of - /// the . - /// Type of the source. - /// Type of the . - public static IDisposable BindTo( - this IObservable sourceObservable, - UICollectionView collectionView, - NSString cellKey, - Action initializeCellAction = null, - Func, IDisposable> initSource = null) - where TCell : UICollectionViewCell - { - return sourceObservable - .Select( - src => new[] - { - new CollectionViewSectionInformation( - src, - cellKey, - initializeCellAction) - }) - .BindTo(collectionView, initSource); - } - - /// - /// Extension method that binds an observable of a collection - /// as the source of a . Also registers - /// the given class with an unspecified cellKey (you should probably - /// not specify any other cellKeys). - /// - /// The used to dispose this binding. - /// Source collection observable. - /// Collection view. - /// Initialize cell action. - /// Optionally initializes some property of - /// the . - /// Type of the source. - /// Type of the . - public static IDisposable BindTo( - this IObservable sourceObservable, - UICollectionView collectionView, - Action initializeCellAction = null, - Func, IDisposable> initSource = null) - where TCell : UICollectionViewCell - { - var type = typeof(TCell); - var cellKey = new NSString(type.ToString()); - collectionView.RegisterClassForCell(type, new NSString(cellKey)); - return sourceObservable - .BindTo(collectionView, cellKey, initializeCellAction, initSource); + base.Dispose(disposing); } } } diff --git a/src/ReactiveUI/Platforms/uikit-common/ReactiveCollectionViewSourceExtensions.cs b/src/ReactiveUI/Platforms/uikit-common/ReactiveCollectionViewSourceExtensions.cs new file mode 100644 index 00000000..1e46c542 --- /dev/null +++ b/src/ReactiveUI/Platforms/uikit-common/ReactiveCollectionViewSourceExtensions.cs @@ -0,0 +1,112 @@ +// 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; +using System.Collections.Generic; +using System.Collections.Specialized; +using System.Linq; +using System.Reactive.Disposables; +using System.Reactive.Linq; +using Foundation; +using ReactiveUI.Legacy; +using UIKit; + +namespace ReactiveUI +{ + /// + /// Extension methods for . + /// + public static class ReactiveCollectionViewSourceExtensions + { + /// + /// Extension method that binds an observable of a list of collection + /// sections as the source of a . + /// If your is also an instance of + /// , then this method + /// will silently update the bindings whenever it changes as well. + /// Otherwise, it will just log a message. + /// + /// The used to dispose this binding. + /// Sections observable. + /// Collection view. + /// Optionally initializes some property of + /// the . + /// Type of the view source. + /// Type of the . + public static IDisposable BindTo( + this IObservable>> sectionsObservable, + UICollectionView collectionView, + Func, IDisposable> initSource = null) + where TCell : UICollectionViewCell + { + var source = new ReactiveCollectionViewSource(collectionView); + initSource?.Invoke(source); + + var bind = sectionsObservable.BindTo(source, x => x.Data); + collectionView.Source = source; + return new CompositeDisposable(bind, source); + } + + /// + /// Extension method that binds an observable of a collection + /// as the source of a . + /// + /// The used to dispose this binding. + /// Source collection observable. + /// Collection view. + /// Cell key. + /// Initialize cell action. + /// Optionally initializes some property of + /// the . + /// Type of the source. + /// Type of the . + public static IDisposable BindTo( + this IObservable sourceObservable, + UICollectionView collectionView, + NSString cellKey, + Action initializeCellAction = null, + Func, IDisposable> initSource = null) + where TCell : UICollectionViewCell + { + return sourceObservable + .Select( + src => new[] + { + new CollectionViewSectionInformation( + src, + cellKey, + initializeCellAction) + }) + .BindTo(collectionView, initSource); + } + + /// + /// Extension method that binds an observable of a collection + /// as the source of a . Also registers + /// the given class with an unspecified cellKey (you should probably + /// not specify any other cellKeys). + /// + /// The used to dispose this binding. + /// Source collection observable. + /// Collection view. + /// Initialize cell action. + /// Optionally initializes some property of + /// the . + /// Type of the source. + /// Type of the . + public static IDisposable BindTo( + this IObservable sourceObservable, + UICollectionView collectionView, + Action initializeCellAction = null, + Func, IDisposable> initSource = null) + where TCell : UICollectionViewCell + { + var type = typeof(TCell); + var cellKey = new NSString(type.ToString()); + collectionView.RegisterClassForCell(type, new NSString(cellKey)); + return sourceObservable + .BindTo(collectionView, cellKey, initializeCellAction, initSource); + } + } +} diff --git a/src/ReactiveUI/Platforms/uikit-common/ReactiveNavigationController.cs b/src/ReactiveUI/Platforms/uikit-common/ReactiveNavigationController.cs index f2af8764..0f2a77cc 100644 --- a/src/ReactiveUI/Platforms/uikit-common/ReactiveNavigationController.cs +++ b/src/ReactiveUI/Platforms/uikit-common/ReactiveNavigationController.cs @@ -4,6 +4,7 @@ using System; using System.ComponentModel; +using System.Diagnostics.CodeAnalysis; using System.Reactive; using System.Reactive.Linq; using System.Reactive.Subjects; @@ -16,8 +17,9 @@ namespace ReactiveUI /// This is a UINavigationController that is both an UINavigationController and has ReactiveObject powers /// (i.e. you can call RaiseAndSetIfChanged). /// - public abstract class ReactiveNavigationController : UINavigationController, - IReactiveNotifyPropertyChanged, IHandleObservableErrors, IReactiveObject, ICanActivate, IActivatable + [SuppressMessage("Design", "CA1010: Implement generic IEnumerable", Justification = "UI Kit exposes IEnumerable")] + [SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:FileMayOnlyContainASingleType", Justification = "Classes with the same class names within.")] + public abstract class ReactiveNavigationController : UINavigationController, IReactiveNotifyPropertyChanged, IHandleObservableErrors, IReactiveObject, ICanActivate, IActivatable { private Subject _activated = new Subject(); private Subject _deactivated = new Subject(); @@ -29,7 +31,6 @@ namespace ReactiveUI protected ReactiveNavigationController(UIViewController rootViewController) : base(rootViewController) { - SetupRxObj(); } /// @@ -40,7 +41,6 @@ namespace ReactiveUI protected ReactiveNavigationController(Type navigationBarType, Type toolbarType) : base(navigationBarType, toolbarType) { - SetupRxObj(); } /// @@ -51,7 +51,6 @@ namespace ReactiveUI protected ReactiveNavigationController(string nibName, NSBundle bundle) : base(nibName, bundle) { - SetupRxObj(); } /// @@ -61,7 +60,6 @@ namespace ReactiveUI protected ReactiveNavigationController(IntPtr handle) : base(handle) { - SetupRxObj(); } /// @@ -71,7 +69,6 @@ namespace ReactiveUI protected ReactiveNavigationController(NSObjectFlag t) : base(t) { - SetupRxObj(); } /// @@ -81,7 +78,6 @@ namespace ReactiveUI protected ReactiveNavigationController(NSCoder coder) : base(coder) { - SetupRxObj(); } /// @@ -89,7 +85,6 @@ namespace ReactiveUI /// protected ReactiveNavigationController() { - SetupRxObj(); } /// @@ -106,15 +101,10 @@ namespace ReactiveUI remove => PropertyChangedEventManager.RemoveHandler(this, value); } - /// - /// Represents an Observable that fires *before* a property is about to - /// be changed. - /// + /// public IObservable> Changing => this.GetChangingObservable(); - /// - /// Represents an Observable that fires *after* a property has changed. - /// + /// public IObservable> Changed => this.GetChangedObservable(); /// @@ -165,10 +155,6 @@ namespace ReactiveUI _deactivated.OnNext(Unit.Default); this.ActivateSubviews(false); } - - private void SetupRxObj() - { - } } /// @@ -176,6 +162,8 @@ namespace ReactiveUI /// (i.e. you can call RaiseAndSetIfChanged). /// /// The view model type. + [SuppressMessage("Design", "CA1010: Implement generic IEnumerable", Justification = "UI Kit exposes IEnumerable")] + [SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:FileMayOnlyContainASingleType", Justification = "Classes with the same class names within.")] public abstract class ReactiveNavigationController : ReactiveNavigationController, IViewFor where TViewModel : class { diff --git a/src/ReactiveUI/Platforms/uikit-common/ReactivePageViewController.cs b/src/ReactiveUI/Platforms/uikit-common/ReactivePageViewController.cs index d36c3a99..65ba0a1d 100644 --- a/src/ReactiveUI/Platforms/uikit-common/ReactivePageViewController.cs +++ b/src/ReactiveUI/Platforms/uikit-common/ReactivePageViewController.cs @@ -4,6 +4,7 @@ using System; using System.ComponentModel; +using System.Diagnostics.CodeAnalysis; using System.Reactive; using System.Reactive.Linq; using System.Reactive.Subjects; @@ -16,8 +17,9 @@ namespace ReactiveUI /// This is a UIPageViewController that is both an UIPageViewController and has ReactiveObject powers /// (i.e. you can call RaiseAndSetIfChanged). /// - public abstract class ReactivePageViewController : UIPageViewController, - IReactiveNotifyPropertyChanged, IHandleObservableErrors, IReactiveObject, ICanActivate + [SuppressMessage("Design", "CA1010: Implement generic IEnumerable", Justification = "UI Kit exposes IEnumerable")] + [SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:FileMayOnlyContainASingleType", Justification = "Classes with the same class names within.")] + public abstract class ReactivePageViewController : UIPageViewController, IReactiveNotifyPropertyChanged, IHandleObservableErrors, IReactiveObject, ICanActivate { private Subject _activated = new Subject(); private Subject _deactivated = new Subject(); @@ -30,7 +32,6 @@ namespace ReactiveUI protected ReactivePageViewController(UIPageViewControllerTransitionStyle style, UIPageViewControllerNavigationOrientation orientation) : base(style, orientation) { - SetupRxObj(); } /// @@ -42,7 +43,6 @@ namespace ReactiveUI protected ReactivePageViewController(UIPageViewControllerTransitionStyle style, UIPageViewControllerNavigationOrientation orientation, NSDictionary options) : base(style, orientation, options) { - SetupRxObj(); } /// @@ -54,7 +54,6 @@ namespace ReactiveUI protected ReactivePageViewController(UIPageViewControllerTransitionStyle style, UIPageViewControllerNavigationOrientation orientation, UIPageViewControllerSpineLocation spineLocation) : base(style, orientation, spineLocation) { - SetupRxObj(); } /// @@ -67,7 +66,6 @@ namespace ReactiveUI protected ReactivePageViewController(UIPageViewControllerTransitionStyle style, UIPageViewControllerNavigationOrientation orientation, UIPageViewControllerSpineLocation spineLocation, float interPageSpacing) : base(style, orientation, spineLocation, interPageSpacing) { - SetupRxObj(); } /// @@ -78,7 +76,6 @@ namespace ReactiveUI protected ReactivePageViewController(string nibName, NSBundle bundle) : base(nibName, bundle) { - SetupRxObj(); } /// @@ -88,7 +85,6 @@ namespace ReactiveUI protected ReactivePageViewController(IntPtr handle) : base(handle) { - SetupRxObj(); } /// @@ -98,7 +94,6 @@ namespace ReactiveUI protected ReactivePageViewController(NSObjectFlag t) : base(t) { - SetupRxObj(); } /// @@ -108,7 +103,6 @@ namespace ReactiveUI protected ReactivePageViewController(NSCoder coder) : base(coder) { - SetupRxObj(); } /// @@ -116,7 +110,6 @@ namespace ReactiveUI /// protected ReactivePageViewController() { - SetupRxObj(); } /// @@ -133,15 +126,10 @@ namespace ReactiveUI remove => PropertyChangedEventManager.RemoveHandler(this, value); } - /// - /// Represents an Observable that fires *before* a property is about to - /// be changed. - /// + /// public IObservable> Changing => this.GetChangingObservable(); - /// - /// Represents an Observable that fires *after* a property has changed. - /// + /// public IObservable> Changed => this.GetChangedObservable(); /// @@ -192,10 +180,6 @@ namespace ReactiveUI _deactivated.OnNext(Unit.Default); this.ActivateSubviews(false); } - - private void SetupRxObj() - { - } } /// @@ -203,6 +187,8 @@ namespace ReactiveUI /// (i.e. you can call RaiseAndSetIfChanged). /// /// The view model type. + [SuppressMessage("Design", "CA1010: Implement generic IEnumerable", Justification = "UI Kit exposes IEnumerable")] + [SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:FileMayOnlyContainASingleType", Justification = "Classes with the same class names within.")] public abstract class ReactivePageViewController : ReactivePageViewController, IViewFor where TViewModel : class { diff --git a/src/ReactiveUI/Platforms/uikit-common/ReactiveTabBarController.cs b/src/ReactiveUI/Platforms/uikit-common/ReactiveTabBarController.cs index 1b39fc2f..3a36dd97 100644 --- a/src/ReactiveUI/Platforms/uikit-common/ReactiveTabBarController.cs +++ b/src/ReactiveUI/Platforms/uikit-common/ReactiveTabBarController.cs @@ -4,6 +4,7 @@ using System; using System.ComponentModel; +using System.Diagnostics.CodeAnalysis; using System.Reactive; using System.Reactive.Linq; using System.Reactive.Subjects; @@ -16,8 +17,9 @@ namespace ReactiveUI /// This is a TabBar that is both an TabBar and has ReactiveObject powers /// (i.e. you can call RaiseAndSetIfChanged). /// - public abstract class ReactiveTabBarController : UITabBarController, - IReactiveNotifyPropertyChanged, IHandleObservableErrors, IReactiveObject, ICanActivate + [SuppressMessage("Design", "CA1010: Implement generic IEnumerable", Justification = "UI Kit exposes IEnumerable")] + [SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:FileMayOnlyContainASingleType", Justification = "Classes with the same class names within.")] + public abstract class ReactiveTabBarController : UITabBarController, IReactiveNotifyPropertyChanged, IHandleObservableErrors, IReactiveObject, ICanActivate { private Subject _activated = new Subject(); private Subject _deactivated = new Subject(); @@ -30,7 +32,6 @@ namespace ReactiveUI protected ReactiveTabBarController(string nibName, NSBundle bundle) : base(nibName, bundle) { - SetupRxObj(); } /// @@ -40,7 +41,6 @@ namespace ReactiveUI protected ReactiveTabBarController(IntPtr handle) : base(handle) { - SetupRxObj(); } /// @@ -50,7 +50,6 @@ namespace ReactiveUI protected ReactiveTabBarController(NSObjectFlag t) : base(t) { - SetupRxObj(); } /// @@ -60,7 +59,6 @@ namespace ReactiveUI protected ReactiveTabBarController(NSCoder coder) : base(coder) { - SetupRxObj(); } /// @@ -68,7 +66,6 @@ namespace ReactiveUI /// protected ReactiveTabBarController() { - SetupRxObj(); } /// @@ -85,15 +82,10 @@ namespace ReactiveUI remove => PropertyChangedEventManager.RemoveHandler(this, value); } - /// - /// Represents an Observable that fires *before* a property is about to - /// be changed. - /// + /// public IObservable> Changing => this.GetChangingObservable(); - /// - /// Represents an Observable that fires *after* a property has changed. - /// + /// public IObservable> Changed => this.GetChangedObservable(); /// @@ -144,10 +136,6 @@ namespace ReactiveUI { PropertyChangedEventManager.DeliverEvent(this, args); } - - private void SetupRxObj() - { - } } /// @@ -155,6 +143,8 @@ namespace ReactiveUI /// (i.e. you can call RaiseAndSetIfChanged). /// /// The view model type. + [SuppressMessage("Design", "CA1010: Implement generic IEnumerable", Justification = "UI Kit exposes IEnumerable")] + [SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:FileMayOnlyContainASingleType", Justification = "Classes with the same class names within.")] public abstract class ReactiveTabBarController : ReactiveTabBarController, IViewFor where TViewModel : class { diff --git a/src/ReactiveUI/Platforms/uikit-common/ReactiveTableView.cs b/src/ReactiveUI/Platforms/uikit-common/ReactiveTableView.cs index 4b32eea7..c6de45ae 100644 --- a/src/ReactiveUI/Platforms/uikit-common/ReactiveTableView.cs +++ b/src/ReactiveUI/Platforms/uikit-common/ReactiveTableView.cs @@ -4,6 +4,7 @@ using System; using System.ComponentModel; +using System.Diagnostics.CodeAnalysis; using System.Reactive; using System.Reactive.Concurrency; using System.Reactive.Linq; @@ -18,6 +19,8 @@ namespace ReactiveUI /// This is a TableView that is both an TableView and has ReactiveObject powers /// (i.e. you can call RaiseAndSetIfChanged). /// + [SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:FileMayOnlyContainASingleType", Justification = "Classes with the same class names within.")] + [SuppressMessage("Design", "CA1010: Implement generic IEnumerable", Justification = "UI Kit exposes IEnumerable")] public abstract class ReactiveTableView : UITableView, IReactiveNotifyPropertyChanged, IHandleObservableErrors, IReactiveObject, ICanActivate, ICanForceManualActivation { private Subject _activated = new Subject(); @@ -90,15 +93,10 @@ namespace ReactiveUI remove => PropertyChangedEventManager.RemoveHandler(this, value); } - /// - /// Represents an Observable that fires *before* a property is about to - /// be changed. - /// + /// public IObservable> Changing => this.GetChangingObservable(); - /// - /// Represents an Observable that fires *after* a property has changed. - /// + /// public IObservable> Changed => this.GetChangedObservable(); /// @@ -148,6 +146,8 @@ namespace ReactiveUI /// (i.e. you can call RaiseAndSetIfChanged). /// /// The view model type. + [SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:FileMayOnlyContainASingleType", Justification = "Classes with the same class names within.")] + [SuppressMessage("Design", "CA1010: Implement generic IEnumerable", Justification = "UI Kit exposes IEnumerable")] public abstract class ReactiveTableView : ReactiveTableView, IViewFor where TViewModel : class { diff --git a/src/ReactiveUI/Platforms/uikit-common/ReactiveTableViewCell.cs b/src/ReactiveUI/Platforms/uikit-common/ReactiveTableViewCell.cs index 5f801b32..f1d59021 100644 --- a/src/ReactiveUI/Platforms/uikit-common/ReactiveTableViewCell.cs +++ b/src/ReactiveUI/Platforms/uikit-common/ReactiveTableViewCell.cs @@ -4,6 +4,7 @@ using System; using System.ComponentModel; +using System.Diagnostics.CodeAnalysis; using System.Reactive; using System.Reactive.Concurrency; using System.Reactive.Linq; @@ -18,6 +19,8 @@ namespace ReactiveUI /// This is a UITableViewCell that is both an UITableViewCell and has ReactiveObject powers /// (i.e. you can call RaiseAndSetIfChanged). /// + [SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:FileMayOnlyContainASingleType", Justification = "Classes with the same class names within.")] + [SuppressMessage("Design", "CA1010: Implement generic IEnumerable", Justification = "UI Kit exposes IEnumerable")] public abstract class ReactiveTableViewCell : UITableViewCell, IReactiveNotifyPropertyChanged, IHandleObservableErrors, IReactiveObject, ICanActivate { private Subject _activated = new Subject(); @@ -30,7 +33,6 @@ namespace ReactiveUI protected ReactiveTableViewCell(CGRect frame) : base(frame) { - SetupRxObj(); } /// @@ -40,17 +42,16 @@ namespace ReactiveUI protected ReactiveTableViewCell(NSObjectFlag t) : base(t) { - SetupRxObj(); } /// /// Initializes a new instance of the class. /// /// The coder. + [SuppressMessage("Redundancy", "CA1801: Redundant parameter", Justification = "Legacy interface")] protected ReactiveTableViewCell(NSCoder coder) : base(NSObjectFlag.Empty) { - SetupRxObj(); } /// @@ -58,7 +59,6 @@ namespace ReactiveUI /// protected ReactiveTableViewCell() { - SetupRxObj(); } /// @@ -69,7 +69,6 @@ namespace ReactiveUI protected ReactiveTableViewCell(UITableViewCellStyle style, string reuseIdentifier) : base(style, reuseIdentifier) { - SetupRxObj(); } /// @@ -80,7 +79,6 @@ namespace ReactiveUI protected ReactiveTableViewCell(UITableViewCellStyle style, NSString reuseIdentifier) : base(style, reuseIdentifier) { - SetupRxObj(); } /// @@ -90,7 +88,6 @@ namespace ReactiveUI protected ReactiveTableViewCell(IntPtr handle) : base(handle) { - SetupRxObj(); } /// @@ -107,15 +104,10 @@ namespace ReactiveUI remove => PropertyChangedEventManager.RemoveHandler(this, value); } - /// - /// Represents an Observable that fires *before* a property is about to - /// be changed. - /// + /// public IObservable> Changing => this.GetChangingObservable(); - /// - /// Represents an Observable that fires *after* a property has changed. - /// + /// public IObservable> Changed => this.GetChangedObservable(); /// @@ -157,10 +149,6 @@ namespace ReactiveUI { PropertyChangedEventManager.DeliverEvent(this, args); } - - private void SetupRxObj() - { - } } /// @@ -168,6 +156,8 @@ namespace ReactiveUI /// (i.e. you can call RaiseAndSetIfChanged). /// /// The view model type. + [SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:FileMayOnlyContainASingleType", Justification = "Classes with the same class names within.")] + [SuppressMessage("Design", "CA1010: Implement generic IEnumerable", Justification = "UI Kit exposes IEnumerable")] public abstract class ReactiveTableViewCell : ReactiveTableViewCell, IViewFor where TViewModel : class { @@ -195,6 +185,7 @@ namespace ReactiveUI /// Initializes a new instance of the class. /// /// The coder. + [SuppressMessage("Redundancy", "CA1801: Redundant parameter", Justification = "Legacy interface")] protected ReactiveTableViewCell(NSCoder coder) : base(NSObjectFlag.Empty) { diff --git a/src/ReactiveUI/Platforms/uikit-common/ReactiveTableViewController.cs b/src/ReactiveUI/Platforms/uikit-common/ReactiveTableViewController.cs index 1376ab30..df90f2ec 100644 --- a/src/ReactiveUI/Platforms/uikit-common/ReactiveTableViewController.cs +++ b/src/ReactiveUI/Platforms/uikit-common/ReactiveTableViewController.cs @@ -4,6 +4,7 @@ using System; using System.ComponentModel; +using System.Diagnostics.CodeAnalysis; using System.Reactive; using System.Reactive.Linq; using System.Reactive.Subjects; @@ -17,8 +18,9 @@ namespace ReactiveUI /// This is a NSTableViewController that is both an NSTableViewController and has ReactiveObject powers /// (i.e. you can call RaiseAndSetIfChanged). /// - public abstract class ReactiveTableViewController : NSTableViewController, - IReactiveNotifyPropertyChanged, IHandleObservableErrors, IReactiveObject, ICanActivate + [SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:FileMayOnlyContainASingleType", Justification = "Classes with the same class names within.")] + [SuppressMessage("Design", "CA1010: Implement generic IEnumerable", Justification = "UI Kit exposes IEnumerable")] + public abstract class ReactiveTableViewController : NSTableViewController, IReactiveNotifyPropertyChanged, IHandleObservableErrors, IReactiveObject, ICanActivate { private Subject _activated = new Subject(); private Subject _deactivated = new Subject(); @@ -30,7 +32,6 @@ namespace ReactiveUI protected ReactiveTableViewController(NSTableViewStyle withStyle) : base(withStyle) { - SetupRxObj(); } /// @@ -41,7 +42,6 @@ namespace ReactiveUI protected ReactiveTableViewController(string nibName, NSBundle bundle) : base(nibName, bundle) { - SetupRxObj(); } /// @@ -51,7 +51,6 @@ namespace ReactiveUI protected ReactiveTableViewController(IntPtr handle) : base(handle) { - SetupRxObj(); } /// @@ -61,7 +60,6 @@ namespace ReactiveUI protected ReactiveTableViewController(NSObjectFlag t) : base(t) { - SetupRxObj(); } /// @@ -71,7 +69,6 @@ namespace ReactiveUI protected ReactiveTableViewController(NSCoder coder) : base(coder) { - SetupRxObj(); } /// @@ -79,7 +76,6 @@ namespace ReactiveUI /// protected ReactiveTableViewController() { - SetupRxObj(); } /// @@ -96,15 +92,10 @@ namespace ReactiveUI remove => PropertyChangedEventManager.RemoveHandler(this, value); } - /// - /// Represents an Observable that fires *before* a property is about to - /// be changed. - /// + /// public IObservable> Changing => this.GetChangingObservable(); - /// - /// Represents an Observable that fires *after* a property has changed. - /// + /// public IObservable> Changed => this.GetChangedObservable(); /// @@ -155,10 +146,6 @@ namespace ReactiveUI { PropertyChangedEventManager.DeliverEvent(this, args); } - - private void SetupRxObj() - { - } } /// @@ -166,6 +153,8 @@ namespace ReactiveUI /// (i.e. you can call RaiseAndSetIfChanged). /// /// The view model type. + [SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:FileMayOnlyContainASingleType", Justification = "Classes with the same class names within.")] + [SuppressMessage("Design", "CA1010: Implement generic IEnumerable", Justification = "UI Kit exposes IEnumerable")] public abstract class ReactiveTableViewController : ReactiveTableViewController, IViewFor where TViewModel : class { diff --git a/src/ReactiveUI/Platforms/uikit-common/ReactiveTableViewSource.cs b/src/ReactiveUI/Platforms/uikit-common/ReactiveTableViewSource.cs index 88e7a473..fc565a21 100644 --- a/src/ReactiveUI/Platforms/uikit-common/ReactiveTableViewSource.cs +++ b/src/ReactiveUI/Platforms/uikit-common/ReactiveTableViewSource.cs @@ -18,134 +18,6 @@ using UIKit; namespace ReactiveUI { - internal class UITableViewAdapter : IUICollViewAdapter - { - private readonly UITableView _view; - private readonly BehaviorSubject _isReloadingData; - private int _inFlightReloads; - - internal UITableViewAdapter(UITableView view) - { - _view = view; - _isReloadingData = new BehaviorSubject(false); - } - - public IObservable IsReloadingData => _isReloadingData.AsObservable(); - - public UITableViewRowAnimation InsertSectionsAnimation { get; set; } = UITableViewRowAnimation.Automatic; - - public UITableViewRowAnimation DeleteSectionsAnimation { get; set; } = UITableViewRowAnimation.Automatic; - - public UITableViewRowAnimation ReloadSectionsAnimation { get; set; } = UITableViewRowAnimation.Automatic; - - public UITableViewRowAnimation InsertRowsAnimation { get; set; } = UITableViewRowAnimation.Automatic; - - public UITableViewRowAnimation DeleteRowsAnimation { get; set; } = UITableViewRowAnimation.Automatic; - - public UITableViewRowAnimation ReloadRowsAnimation { get; set; } = UITableViewRowAnimation.Automatic; - - public void ReloadData() - { - ++_inFlightReloads; - _view.ReloadData(); - - if (_inFlightReloads == 1) - { - Debug.Assert(!_isReloadingData.Value); - _isReloadingData.OnNext(true); - } - - // since ReloadData() queues the appropriate messages on the UI thread, we know we're done reloading - // when this subsequent message is processed (with one caveat - see FinishReloadData for details) - RxApp.MainThreadScheduler.Schedule(FinishReloadData); - } - - public void BeginUpdates() - { - _view.BeginUpdates(); - } - - public void PerformUpdates(Action updates, Action completion) - { - _view.BeginUpdates(); - try - { - updates(); - } - finally - { - _view.EndUpdates(); - completion(); - } - } - - public void EndUpdates() - { - _view.EndUpdates(); - } - - public void InsertSections(NSIndexSet indexes) - { - _view.InsertSections(indexes, InsertSectionsAnimation); - } - - public void DeleteSections(NSIndexSet indexes) - { - _view.DeleteSections(indexes, DeleteSectionsAnimation); - } - - public void ReloadSections(NSIndexSet indexes) - { - _view.ReloadSections(indexes, ReloadSectionsAnimation); - } - - public void MoveSection(int fromIndex, int toIndex) - { - _view.MoveSection(fromIndex, toIndex); - } - - public void InsertItems(NSIndexPath[] paths) - { - _view.InsertRows(paths, InsertRowsAnimation); - } - - public void DeleteItems(NSIndexPath[] paths) - { - _view.DeleteRows(paths, DeleteRowsAnimation); - } - - public void ReloadItems(NSIndexPath[] paths) - { - _view.ReloadRows(paths, ReloadRowsAnimation); - } - - public void MoveItem(NSIndexPath path, NSIndexPath newPath) - { - _view.MoveRow(path, newPath); - } - - public UITableViewCell DequeueReusableCell(NSString cellKey, NSIndexPath path) - { - return _view.DequeueReusableCell(cellKey, path); - } - - private void FinishReloadData() - { - --_inFlightReloads; - - if (_inFlightReloads == 0) - { - // this is required because sometimes iOS schedules further work that results in calls to GetCell - // that work could happen after FinishReloadData unless we force layout here - // of course, we can't have that work running after IsReloading ticks to false because otherwise - // some updates may occur before the calls to GetCell and thus the calls to GetCell could fail due to invalid indexes - _view.LayoutIfNeeded(); - Debug.Assert(_isReloadingData.Value); - _isReloadingData.OnNext(false); - } - } - } - /// /// ReactiveTableViewSource is a Table View Source that is connected to /// a List that automatically updates the View based on the @@ -153,7 +25,7 @@ namespace ReactiveUI /// items are animated in and out as items are added. /// /// The source type. - public class ReactiveTableViewSource : UITableViewSource, IEnableLogger, IDisposable, IReactiveNotifyPropertyChanged>, IHandleObservableErrors, IReactiveObject + public class ReactiveTableViewSource : UITableViewSource, IEnableLogger, IReactiveNotifyPropertyChanged>, IHandleObservableErrors, IReactiveObject { private readonly CommonReactiveSource> _commonSource; private readonly Subject _elementSelected = new Subject(); @@ -188,11 +60,24 @@ namespace ReactiveUI /// The table view. public ReactiveTableViewSource(UITableView tableView) { - SetupRxObj(); _adapter = new UITableViewAdapter(tableView); _commonSource = new CommonReactiveSource>(_adapter); } + /// + public event PropertyChangingEventHandler PropertyChanging + { + add => PropertyChangingEventManager.AddHandler(this, value); + remove => PropertyChangingEventManager.RemoveHandler(this, value); + } + + /// + public event PropertyChangedEventHandler PropertyChanged + { + add => PropertyChangedEventManager.AddHandler(this, value); + remove => PropertyChangedEventManager.RemoveHandler(this, value); + } + /// /// Gets or sets the data that should be displayed by this /// . You should @@ -277,6 +162,15 @@ namespace ReactiveUI set => _adapter.ReloadRowsAnimation = value; } + /// + public IObservable>> Changing => this.GetChangingObservable(); + + /// + public IObservable>> Changed => this.GetChangedObservable(); + + /// + public IObservable ThrownExceptions => this.GetThrownExceptionsObservable(); + /// public override UITableViewCell GetCell(UITableView tableView, NSIndexPath indexPath) { @@ -314,17 +208,6 @@ namespace ReactiveUI _elementSelected.OnNext(_commonSource.ItemAt(indexPath)); } - /// - protected override void Dispose(bool disposing) - { - if (disposing) - { - _commonSource.Dispose(); - } - - base.Dispose(disposing); - } - /// public override nfloat GetHeightForRow(UITableView tableView, NSIndexPath indexPath) => _commonSource.SectionInfo[indexPath.Section].SizeHint; @@ -393,50 +276,6 @@ namespace ReactiveUI /// The item. public object ItemAt(NSIndexPath indexPath) => _commonSource.ItemAt(indexPath); - /// - public event PropertyChangingEventHandler PropertyChanging - { - add => PropertyChangingEventManager.AddHandler(this, value); - remove => PropertyChangingEventManager.RemoveHandler(this, value); - } - - /// - void IReactiveObject.RaisePropertyChanging(PropertyChangingEventArgs args) - { - PropertyChangingEventManager.DeliverEvent(this, args); - } - - /// - public event PropertyChangedEventHandler PropertyChanged - { - add => PropertyChangedEventManager.AddHandler(this, value); - remove => PropertyChangedEventManager.RemoveHandler(this, value); - } - - /// - void IReactiveObject.RaisePropertyChanged(PropertyChangedEventArgs args) - { - PropertyChangedEventManager.DeliverEvent(this, args); - } - - /// - /// Represents an Observable that fires *before* a property is about to - /// be changed. - /// - public IObservable>> Changing => this.GetChangingObservable(); - - /// - /// Represents an Observable that fires *after* a property has changed. - /// - public IObservable>> Changed => this.GetChangedObservable(); - - /// - public IObservable ThrownExceptions => this.GetThrownExceptionsObservable(); - - private void SetupRxObj() - { - } - /// /// When this method is called, an object will not fire change /// notifications (neither traditional nor Observable notifications) @@ -448,5 +287,28 @@ namespace ReactiveUI { return IReactiveObjectExtensions.SuppressChangeNotifications(this); } + + /// + void IReactiveObject.RaisePropertyChanging(PropertyChangingEventArgs args) + { + PropertyChangingEventManager.DeliverEvent(this, args); + } + + /// + void IReactiveObject.RaisePropertyChanged(PropertyChangedEventArgs args) + { + PropertyChangedEventManager.DeliverEvent(this, args); + } + + /// + protected override void Dispose(bool disposing) + { + if (disposing) + { + _commonSource.Dispose(); + } + + base.Dispose(disposing); + } } } diff --git a/src/ReactiveUI/Platforms/uikit-common/ReactiveTableViewSourceExtensions.cs b/src/ReactiveUI/Platforms/uikit-common/ReactiveTableViewSourceExtensions.cs index bd13bdf0..dd7a0667 100644 --- a/src/ReactiveUI/Platforms/uikit-common/ReactiveTableViewSourceExtensions.cs +++ b/src/ReactiveUI/Platforms/uikit-common/ReactiveTableViewSourceExtensions.cs @@ -17,7 +17,7 @@ namespace ReactiveUI /// Extension method that binds an observable of a list of table /// sections as the source of a . /// If your is also an instance of - /// , then this method + /// , then this method /// will silently update the bindings whenever it changes as well. /// Otherwise, it will just log a message. /// @@ -112,4 +112,4 @@ namespace ReactiveUI .BindTo(tableView, cellKey, sizeHint, initializeCellAction, initSource); } } -} \ No newline at end of file +} diff --git a/src/ReactiveUI/Platforms/uikit-common/RoutedViewHost.cs b/src/ReactiveUI/Platforms/uikit-common/RoutedViewHost.cs index 3a5098d7..7cb03dc9 100644 --- a/src/ReactiveUI/Platforms/uikit-common/RoutedViewHost.cs +++ b/src/ReactiveUI/Platforms/uikit-common/RoutedViewHost.cs @@ -4,13 +4,12 @@ using System; using System.Collections.Specialized; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Reactive.Disposables; using System.Reactive.Linq; using DynamicData; using DynamicData.Binding; -using UIKit; -using NSView = UIKit.UIView; using NSViewController = UIKit.UIViewController; namespace ReactiveUI @@ -19,6 +18,7 @@ namespace ReactiveUI /// RoutedViewHost is a ReactiveNavigationController that monitors its RoutingState /// and keeps the navigation stack in line with it. /// + [SuppressMessage("Design", "CA1010: Implement generic IEnumerable", Justification = "UI Kit exposes IEnumerable")] public class RoutedViewHost : ReactiveNavigationController { private readonly SerialDisposable _titleUpdater; @@ -26,29 +26,6 @@ namespace ReactiveUI private IObservable _viewContractObservable; private bool _routerInstigated; - /// - /// Gets or sets the of the view model stack. - /// - public RoutingState Router - { - get => _router; - set => this.RaiseAndSetIfChanged(ref _router, value); - } - - /// - /// Gets or sets the view contract observable. - /// - public IObservable ViewContractObservable - { - get => _viewContractObservable; - set => this.RaiseAndSetIfChanged(ref _viewContractObservable, value); - } - - /// - /// Gets or sets the view locator. - /// - public IViewLocator ViewLocator { get; set; } - /// /// Initializes a new instance of the class. /// @@ -88,7 +65,7 @@ namespace ReactiveUI d(navigationStackChanged .Where(x => x.EventArgs.Action == NotifyCollectionChangedAction.Add) - .Select(contract => new { View = ResolveView(Router.GetCurrentViewModel(), /*contract*/null), Animate = Router.NavigationStack.Count > 1 }) + .Select(_ => new { View = ResolveView(Router.GetCurrentViewModel(), /*contract*/null), Animate = Router.NavigationStack.Count > 1 }) .Subscribe(x => { if (_routerInstigated) @@ -129,6 +106,29 @@ namespace ReactiveUI }); } + /// + /// Gets or sets the of the view model stack. + /// + public RoutingState Router + { + get => _router; + set => this.RaiseAndSetIfChanged(ref _router, value); + } + + /// + /// Gets or sets the view contract observable. + /// + public IObservable ViewContractObservable + { + get => _viewContractObservable; + set => this.RaiseAndSetIfChanged(ref _viewContractObservable, value); + } + + /// + /// Gets or sets the view locator. + /// + public IViewLocator ViewLocator { get; set; } + /// public override void PushViewController(NSViewController viewController, bool animated) { @@ -156,7 +156,7 @@ namespace ReactiveUI return base.PopViewController(animated); } - private UIViewController ResolveView(IRoutableViewModel viewModel, string contract) + private NSViewController ResolveView(IRoutableViewModel viewModel, string contract) { if (viewModel == null) { @@ -172,9 +172,8 @@ namespace ReactiveUI } view.ViewModel = viewModel; - var viewController = view as UIViewController; - if (viewController == null) + if (!(view is NSViewController viewController)) { throw new Exception($"View type {view.GetType().Name} for view model type {viewModel.GetType().Name} is not a UIViewController"); } @@ -182,95 +181,4 @@ namespace ReactiveUI return viewController; } } - - /// - /// RoutedViewHost is a helper class that will connect a RoutingState - /// to an arbitrary NSView and attempt to load the View for the latest - /// ViewModel as a child view of the target. Usually the target view will - /// be the NSWindow. - /// - /// This is a bit different than the XAML's RoutedViewHost in the sense - /// that this isn't a Control itself, it only manipulates other Views. - /// - [Obsolete("Use RoutedViewHost instead. This class will be removed in a later release.")] - public class RoutedViewHostLegacy : ReactiveObject - { - private RoutingState _router; - -#pragma warning disable SA1600 // Elements should be documented - public RoutingState Router - { - get => _router; - set => this.RaiseAndSetIfChanged(ref _router, value); - } - - private IObservable _viewContractObservable; - - public IObservable ViewContractObservable - { - get => _viewContractObservable; - set => this.RaiseAndSetIfChanged(ref _viewContractObservable, value); - } - - private NSViewController _defaultContent; - - public NSViewController DefaultContent - { - get => _defaultContent; - set => this.RaiseAndSetIfChanged(ref _defaultContent, value); - } - - public IViewLocator ViewLocator { get; set; } - - public RoutedViewHostLegacy(NSView targetView) - { - NSView viewLastAdded = null; - - ViewContractObservable = Observable.Return(default(string)); - - var vmAndContract = Observable.CombineLatest( - this.WhenAnyObservable(x => x.Router.CurrentViewModel), - this.WhenAnyObservable(x => x.ViewContractObservable), - (vm, contract) => new { ViewModel = vm, Contract = contract, }); - - vmAndContract.Subscribe( - x => - { - if (viewLastAdded != null) - { - viewLastAdded.RemoveFromSuperview(); - } - - if (x.ViewModel == null) - { - if (DefaultContent != null) - { - targetView.AddSubview(DefaultContent.View); - } - - return; - } - - var viewLocator = ViewLocator ?? ReactiveUI.ViewLocator.Current; - var view = viewLocator.ResolveView(x.ViewModel, x.Contract) ?? viewLocator.ResolveView(x.ViewModel, null); - view.ViewModel = x.ViewModel; - - if (view is NSViewController) - { - viewLastAdded = ((NSViewController)view).View; - } - else if (view is NSView) - { - viewLastAdded = (NSView)view; - } - else - { - throw new Exception($"'{view.GetType().FullName}' must be an NSViewController or NSView"); - } - - targetView.AddSubview(viewLastAdded); - }, RxApp.DefaultExceptionHandler.OnNext); - } -#pragma warning restore SA1600 // Elements should be documented - } } diff --git a/src/ReactiveUI/Platforms/uikit-common/SectionInfoIdGenerator.cs b/src/ReactiveUI/Platforms/uikit-common/SectionInfoIdGenerator.cs new file mode 100644 index 00000000..aea9fa81 --- /dev/null +++ b/src/ReactiveUI/Platforms/uikit-common/SectionInfoIdGenerator.cs @@ -0,0 +1,16 @@ +// 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. + +namespace ReactiveUI +{ + internal static class SectionInfoIdGenerator + { + private static int nextSectionInfoId; + + public static int Generate() + { + return nextSectionInfoId++; + } + } +} diff --git a/src/ReactiveUI/Platforms/uikit-common/TableSectionHeader.cs b/src/ReactiveUI/Platforms/uikit-common/TableSectionHeader.cs index 558aef3c..7c882be2 100644 --- a/src/ReactiveUI/Platforms/uikit-common/TableSectionHeader.cs +++ b/src/ReactiveUI/Platforms/uikit-common/TableSectionHeader.cs @@ -9,24 +9,7 @@ namespace ReactiveUI public class TableSectionHeader { /// - /// Gets the function that creates the - /// used as header for this section. Overrides Title. - /// - public Func View { get; protected set; } - - /// - /// Gets the height of the header. - /// - public float Height { get; protected set; } - - /// - /// Gets the title for the section header, only used if View is null. - /// - public string Title { get; protected set; } - - /// - /// Initializes a new instance of the - /// struct. + /// Initializes a new instance of the class. /// /// Function that creates header's . /// Height of the header. @@ -44,5 +27,21 @@ namespace ReactiveUI { Title = title; } + + /// + /// Gets or sets the function that creates the + /// used as header for this section. Overrides Title. + /// + public Func View { get; protected set; } + + /// + /// Gets or sets the height of the header. + /// + public float Height { get; protected set; } + + /// + /// Gets or sets the title for the section header, only used if View is null. + /// + public string Title { get; protected set; } } -} \ No newline at end of file +} diff --git a/src/ReactiveUI/Platforms/uikit-common/TableSectionInformation.cs b/src/ReactiveUI/Platforms/uikit-common/TableSectionInformation.cs index 73ec72ee..a0439921 100644 --- a/src/ReactiveUI/Platforms/uikit-common/TableSectionInformation.cs +++ b/src/ReactiveUI/Platforms/uikit-common/TableSectionInformation.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Specialized; +using System.Diagnostics.CodeAnalysis; using Foundation; using UIKit; @@ -10,6 +11,7 @@ namespace ReactiveUI /// and . /// /// The type of the source. + [SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:FileMayOnlyContainASingleType", Justification = "Classes with the same class names within.")] public class TableSectionInformation : ISectionInformation { /// @@ -45,6 +47,7 @@ namespace ReactiveUI /// /// The type of the source. /// The type of the cell. + [SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:FileMayOnlyContainASingleType", Justification = "Classes with the same class names within.")] public class TableSectionInformation : TableSectionInformation where TCell : UITableViewCell { diff --git a/src/ReactiveUI/Platforms/uikit-common/UICollectionViewAdapter.cs b/src/ReactiveUI/Platforms/uikit-common/UICollectionViewAdapter.cs new file mode 100644 index 00000000..dd30babb --- /dev/null +++ b/src/ReactiveUI/Platforms/uikit-common/UICollectionViewAdapter.cs @@ -0,0 +1,143 @@ +// 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; +using System.Diagnostics; +using System.Reactive.Concurrency; +using System.Reactive.Linq; +using System.Reactive.Subjects; +using Foundation; +using UIKit; +using NSAction = System.Action; + +namespace ReactiveUI +{ + internal class UICollectionViewAdapter : IUICollViewAdapter, IDisposable + { + private readonly UICollectionView _view; + private readonly BehaviorSubject _isReloadingData; + private int _inFlightReloads; + private bool _isDisposed; + + internal UICollectionViewAdapter(UICollectionView view) + { + _view = view; + _isReloadingData = new BehaviorSubject(false); + } + + public IObservable IsReloadingData => _isReloadingData.AsObservable(); + + public void ReloadData() + { + ++_inFlightReloads; + _view.ReloadData(); + + if (_inFlightReloads == 1) + { + Debug.Assert(!_isReloadingData.Value, "There is a reload already happening"); + _isReloadingData.OnNext(true); + } + + // since ReloadData() queues the appropriate messages on the UI thread, we know we're done reloading + // when this subsequent message is processed (with one caveat - see FinishReloadData for details) + RxApp.MainThreadScheduler.Schedule(FinishReloadData); + } + + // UICollectionView no longer has these methods so these are no-ops + public void BeginUpdates() + { + } + + public void EndUpdates() + { + } + + public void PerformUpdates(Action updates, Action completion) + { + _view.PerformBatchUpdates(new NSAction(updates), (completed) => completion()); + } + + public void InsertSections(NSIndexSet indexes) + { + _view.InsertSections(indexes); + } + + public void DeleteSections(NSIndexSet indexes) + { + _view.DeleteSections(indexes); + } + + public void ReloadSections(NSIndexSet indexes) + { + _view.ReloadSections(indexes); + } + + public void MoveSection(int fromIndex, int toIndex) + { + _view.MoveSection(fromIndex, toIndex); + } + + public void InsertItems(NSIndexPath[] paths) + { + _view.InsertItems(paths); + } + + public void DeleteItems(NSIndexPath[] paths) + { + _view.DeleteItems(paths); + } + + public void ReloadItems(NSIndexPath[] paths) + { + _view.ReloadItems(paths); + } + + public void MoveItem(NSIndexPath path, NSIndexPath newPath) + { + _view.MoveItem(path, newPath); + } + + public UICollectionViewCell DequeueReusableCell(NSString cellKey, NSIndexPath path) + { + return (UICollectionViewCell)_view.DequeueReusableCell(cellKey, path); + } + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + protected virtual void Dispose(bool isDisposing) + { + if (_isDisposed) + { + return; + } + + if (isDisposing) + { + _isReloadingData?.Dispose(); + } + + _isDisposed = true; + } + + private void FinishReloadData() + { + --_inFlightReloads; + + if (_inFlightReloads == 0) + { + // this is required because sometimes iOS schedules further work that results in calls to GetCell + // that work could happen after FinishReloadData unless we force layout here + // of course, we can't have that work running after IsReloading ticks to false because otherwise + // some updates may occur before the calls to GetCell and thus the calls to GetCell could fail due to invalid indexes + _view.LayoutIfNeeded(); + Debug.Assert(_isReloadingData.Value, "There are no reloads happening"); + _isReloadingData.OnNext(false); + } + } + } +} diff --git a/src/ReactiveUI/Platforms/uikit-common/UITableViewAdapter.cs b/src/ReactiveUI/Platforms/uikit-common/UITableViewAdapter.cs new file mode 100644 index 00000000..1c88d63a --- /dev/null +++ b/src/ReactiveUI/Platforms/uikit-common/UITableViewAdapter.cs @@ -0,0 +1,162 @@ +// 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; +using System.Diagnostics; +using System.Reactive.Concurrency; +using System.Reactive.Linq; +using System.Reactive.Subjects; +using Foundation; +using UIKit; + +namespace ReactiveUI +{ + internal class UITableViewAdapter : IUICollViewAdapter, IDisposable + { + private readonly UITableView _view; + private readonly BehaviorSubject _isReloadingData; + private int _inFlightReloads; + private bool _isDisposed; + + internal UITableViewAdapter(UITableView view) + { + _view = view; + _isReloadingData = new BehaviorSubject(false); + } + + public IObservable IsReloadingData => _isReloadingData.AsObservable(); + + public UITableViewRowAnimation InsertSectionsAnimation { get; set; } = UITableViewRowAnimation.Automatic; + + public UITableViewRowAnimation DeleteSectionsAnimation { get; set; } = UITableViewRowAnimation.Automatic; + + public UITableViewRowAnimation ReloadSectionsAnimation { get; set; } = UITableViewRowAnimation.Automatic; + + public UITableViewRowAnimation InsertRowsAnimation { get; set; } = UITableViewRowAnimation.Automatic; + + public UITableViewRowAnimation DeleteRowsAnimation { get; set; } = UITableViewRowAnimation.Automatic; + + public UITableViewRowAnimation ReloadRowsAnimation { get; set; } = UITableViewRowAnimation.Automatic; + + public void ReloadData() + { + ++_inFlightReloads; + _view.ReloadData(); + + if (_inFlightReloads == 1) + { + Debug.Assert(!_isReloadingData.Value, "There is reload already happening."); + _isReloadingData.OnNext(true); + } + + // since ReloadData() queues the appropriate messages on the UI thread, we know we're done reloading + // when this subsequent message is processed (with one caveat - see FinishReloadData for details) + RxApp.MainThreadScheduler.Schedule(FinishReloadData); + } + + public void BeginUpdates() + { + _view.BeginUpdates(); + } + + public void PerformUpdates(Action updates, Action completion) + { + _view.BeginUpdates(); + try + { + updates(); + } + finally + { + _view.EndUpdates(); + completion(); + } + } + + public void EndUpdates() + { + _view.EndUpdates(); + } + + public void InsertSections(NSIndexSet indexes) + { + _view.InsertSections(indexes, InsertSectionsAnimation); + } + + public void DeleteSections(NSIndexSet indexes) + { + _view.DeleteSections(indexes, DeleteSectionsAnimation); + } + + public void ReloadSections(NSIndexSet indexes) + { + _view.ReloadSections(indexes, ReloadSectionsAnimation); + } + + public void MoveSection(int fromIndex, int toIndex) + { + _view.MoveSection(fromIndex, toIndex); + } + + public void InsertItems(NSIndexPath[] paths) + { + _view.InsertRows(paths, InsertRowsAnimation); + } + + public void DeleteItems(NSIndexPath[] paths) + { + _view.DeleteRows(paths, DeleteRowsAnimation); + } + + public void ReloadItems(NSIndexPath[] paths) + { + _view.ReloadRows(paths, ReloadRowsAnimation); + } + + public void MoveItem(NSIndexPath path, NSIndexPath newPath) + { + _view.MoveRow(path, newPath); + } + + public UITableViewCell DequeueReusableCell(NSString cellKey, NSIndexPath path) + { + return _view.DequeueReusableCell(cellKey, path); + } + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + protected virtual void Dispose(bool disposing) + { + if (!_isDisposed) + { + if (disposing) + { + _isReloadingData?.Dispose(); + } + + _isDisposed = true; + } + } + + private void FinishReloadData() + { + --_inFlightReloads; + + if (_inFlightReloads == 0) + { + // this is required because sometimes iOS schedules further work that results in calls to GetCell + // that work could happen after FinishReloadData unless we force layout here + // of course, we can't have that work running after IsReloading ticks to false because otherwise + // some updates may occur before the calls to GetCell and thus the calls to GetCell could fail due to invalid indexes + _view.LayoutIfNeeded(); + Debug.Assert(_isReloadingData.Value, "There are no reloads happening"); + _isReloadingData.OnNext(false); + } + } + } +} diff --git a/src/ReactiveUI/Platforms/windows-common/AutoDataTemplateBindingHook.cs b/src/ReactiveUI/Platforms/windows-common/AutoDataTemplateBindingHook.cs index c280d260..fe480294 100644 --- a/src/ReactiveUI/Platforms/windows-common/AutoDataTemplateBindingHook.cs +++ b/src/ReactiveUI/Platforms/windows-common/AutoDataTemplateBindingHook.cs @@ -25,9 +25,9 @@ namespace ReactiveUI public class AutoDataTemplateBindingHook : IPropertyBindingHook { /// - /// The default item template. + /// Gets the default item template. /// - public static Lazy DefaultItemTemplate = new Lazy(() => + public static Lazy DefaultItemTemplate { get; } = new Lazy(() => { #if NETFX_CORE const string template = "" + @@ -36,9 +36,10 @@ namespace ReactiveUI return (DataTemplate)XamlReader.Load(template); #else const string template = " " + - "" + - ""; + "xmlns:xaml='clr-namespace:ReactiveUI;assembly=__ASSEMBLYNAME__'> " + + "" + + ""; + var assemblyName = typeof(AutoDataTemplateBindingHook).Assembly.FullName; assemblyName = assemblyName.Substring(0, assemblyName.IndexOf(',')); diff --git a/src/ReactiveUI/Platforms/windows-common/BooleanToVisibilityHint.cs b/src/ReactiveUI/Platforms/windows-common/BooleanToVisibilityHint.cs new file mode 100644 index 00000000..242e4b9a --- /dev/null +++ b/src/ReactiveUI/Platforms/windows-common/BooleanToVisibilityHint.cs @@ -0,0 +1,35 @@ +using System; +using System.Diagnostics.CodeAnalysis; +#if NETFX_CORE +using Windows.UI.Xaml; +#else +using System.Windows; +#endif + +namespace ReactiveUI +{ + /// + /// Enum that hints at the visibility of a ui element. + /// + [SuppressMessage("Name", "CA1714: Flags enums should have plural names", Justification = "For legacy support")] + [Flags] + public enum BooleanToVisibilityHint + { + /// + /// Do not modify the boolean type conversion from it's default action of using the Visibility.Collapsed. + /// + None = 0, + + /// + /// Inverse the action of the boolean type conversion, when it's true collapse the visibility. + /// + Inverse = 1 << 1, + +#if !NETFX_CORE + /// + /// Use the hidden version rather than the Collapsed. + /// + UseHidden = 1 << 2, +#endif + } +} diff --git a/src/ReactiveUI/Platforms/windows-common/BindingTypeConverters.cs b/src/ReactiveUI/Platforms/windows-common/BooleanToVisibilityTypeConverter.cs similarity index 74% rename from src/ReactiveUI/Platforms/windows-common/BindingTypeConverters.cs rename to src/ReactiveUI/Platforms/windows-common/BooleanToVisibilityTypeConverter.cs index 12735d3d..37fa174b 100644 --- a/src/ReactiveUI/Platforms/windows-common/BindingTypeConverters.cs +++ b/src/ReactiveUI/Platforms/windows-common/BooleanToVisibilityTypeConverter.cs @@ -11,30 +11,6 @@ using System.Windows; namespace ReactiveUI { - /// - /// Enum that hints at the visibility of a ui element. - /// - [Flags] - public enum BooleanToVisibilityHint - { - /// - /// Do not modify the boolean type conversion from it's default action of using the Visibility.Collapsed. - /// - None = 0, - - /// - /// Inverse the action of the boolean type conversion, when it's true collapse the visibility. - /// - Inverse = 1 << 1, - -#if !NETFX_CORE - /// - /// Use the hidden version rather than the Collapsed. - /// - UseHidden = 1 << 2, -#endif - } - /// /// This type convert converts between Boolean and XAML Visibility - the /// conversionHint is a BooleanToVisibilityHint. diff --git a/src/ReactiveUI/Platforms/windows-common/ReactiveUserControl.cs b/src/ReactiveUI/Platforms/windows-common/ReactiveUserControl.cs index 996c9b00..5e0efe61 100755 --- a/src/ReactiveUI/Platforms/windows-common/ReactiveUserControl.cs +++ b/src/ReactiveUI/Platforms/windows-common/ReactiveUserControl.cs @@ -71,11 +71,6 @@ namespace ReactiveUI UserControl, IViewFor where TViewModel : class { - /// - /// Gets the binding root view model. - /// - public TViewModel BindingRoot => ViewModel; - /// /// The view model dependency property. /// @@ -86,6 +81,11 @@ namespace ReactiveUI typeof(ReactiveUserControl), new PropertyMetadata(null)); + /// + /// Gets the binding root view model. + /// + public TViewModel BindingRoot => ViewModel; + /// public TViewModel ViewModel { diff --git a/src/ReactiveUI/Platforms/windows-common/RoutedViewHost.cs b/src/ReactiveUI/Platforms/windows-common/RoutedViewHost.cs index ea55a53b..b6747a23 100644 --- a/src/ReactiveUI/Platforms/windows-common/RoutedViewHost.cs +++ b/src/ReactiveUI/Platforms/windows-common/RoutedViewHost.cs @@ -6,8 +6,6 @@ using System; using System.Collections.Generic; using System.Linq; using System.Reactive.Linq; -using System.Reactive.Subjects; -using System.Text; using System.Windows; using ReactiveUI; using Splat; @@ -28,63 +26,24 @@ namespace ReactiveUI /// public class RoutedViewHost : TransitioningContentControl, IActivatable, IEnableLogger { - /// - /// Gets or sets the of the view model stack. - /// - public RoutingState Router - { - get => (RoutingState)GetValue(RouterProperty); - set => SetValue(RouterProperty, value); - } - /// /// The router dependency property. /// public static readonly DependencyProperty RouterProperty = DependencyProperty.Register("Router", typeof(RoutingState), typeof(RoutedViewHost), new PropertyMetadata(null)); - /// - /// This content is displayed whenever there is no page currently - /// routed. - /// - public object DefaultContent - { - get => (object)GetValue(DefaultContentProperty); - set => SetValue(DefaultContentProperty, value); - } - /// /// The default content property. /// public static readonly DependencyProperty DefaultContentProperty = DependencyProperty.Register("DefaultContent", typeof(object), typeof(RoutedViewHost), new PropertyMetadata(null)); - /// - /// Gets or sets the view contract observable. - /// - /// - /// The view contract observable. - /// - public IObservable ViewContractObservable - { - get => (IObservable)GetValue(ViewContractObservableProperty); - set => SetValue(ViewContractObservableProperty, value); - } - /// /// The view contract observable property. /// public static readonly DependencyProperty ViewContractObservableProperty = DependencyProperty.Register("ViewContractObservable", typeof(IObservable), typeof(RoutedViewHost), new PropertyMetadata(Observable.Default)); - /// - /// Gets or sets the view locator. - /// - /// - /// The view locator. - /// - public IViewLocator ViewLocator { get; set; } - /// /// Initializes a new instance of the class. /// @@ -154,5 +113,44 @@ namespace ReactiveUI }, ex => RxApp.DefaultExceptionHandler.OnNext(ex))); }); } + + /// + /// Gets or sets the of the view model stack. + /// + public RoutingState Router + { + get => (RoutingState)GetValue(RouterProperty); + set => SetValue(RouterProperty, value); + } + + /// + /// Gets or sets the content displayed whenever there is no page currently + /// routed. + /// + public object DefaultContent + { + get => (object)GetValue(DefaultContentProperty); + set => SetValue(DefaultContentProperty, value); + } + + /// + /// Gets or sets the view contract observable. + /// + /// + /// The view contract observable. + /// + public IObservable ViewContractObservable + { + get => (IObservable)GetValue(ViewContractObservableProperty); + set => SetValue(ViewContractObservableProperty, value); + } + + /// + /// Gets or sets the view locator. + /// + /// + /// The view locator. + /// + public IViewLocator ViewLocator { get; set; } } } diff --git a/src/ReactiveUI/Platforms/windows-common/ViewModelViewHost.cs b/src/ReactiveUI/Platforms/windows-common/ViewModelViewHost.cs index e539390a..62b3e687 100644 --- a/src/ReactiveUI/Platforms/windows-common/ViewModelViewHost.cs +++ b/src/ReactiveUI/Platforms/windows-common/ViewModelViewHost.cs @@ -23,7 +23,7 @@ namespace ReactiveUI /// the ViewModel property and display it. This control is very useful /// inside a DataTemplate to display the View associated with a ViewModel. /// - public class ViewModelViewHost : TransitioningContentControl, IViewFor, IEnableLogger + public class ViewModelViewHost : TransitioningContentControl, IViewFor, IEnableLogger, IDisposable { /// /// The view model dependency property. @@ -45,6 +45,7 @@ namespace ReactiveUI private readonly Subject _updateViewModel = new Subject(); private string _viewContract; + private bool _isDisposed; /// /// Initializes a new instance of the class. @@ -124,7 +125,7 @@ namespace ReactiveUI } /// - /// If no ViewModel is displayed, this content (i.e. a control) will be displayed. + /// Gets or sets the content displayed by default when no content is set. /// public object DefaultContent { @@ -133,7 +134,7 @@ namespace ReactiveUI } /// - /// The ViewModel to display. + /// Gets or sets the ViewModel to display. /// public object ViewModel { @@ -155,6 +156,32 @@ namespace ReactiveUI /// public IViewLocator ViewLocator { get; set; } + /// + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + /// + /// Disposes of resources inside the class. + /// + /// If we are disposing managed resources. + protected virtual void Dispose(bool isDisposing) + { + if (_isDisposed) + { + return; + } + + if (isDisposing) + { + _updateViewModel?.Dispose(); + } + + _isDisposed = true; + } + private static void SomethingChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs) { ((ViewModelViewHost)dependencyObject)._updateViewModel.OnNext(Unit.Default); diff --git a/src/ReactiveUI/ReactiveCommand/IReactiveCommand.cs b/src/ReactiveUI/ReactiveCommand/IReactiveCommand.cs index b211c497..9dfb2ef0 100644 --- a/src/ReactiveUI/ReactiveCommand/IReactiveCommand.cs +++ b/src/ReactiveUI/ReactiveCommand/IReactiveCommand.cs @@ -12,7 +12,7 @@ namespace ReactiveUI /// Not meant for external use due to the fact it doesn't implement ICommand /// to force the user to favor the Reactive style command execution. /// - internal interface IReactiveCommand : IDisposable, IHandleObservableErrors + public interface IReactiveCommand : IDisposable, IHandleObservableErrors { /// /// Gets an observable whose value indicates whether the command is currently executing. diff --git a/src/ReactiveUI/ReactiveCommand/ReactiveCommand.cs b/src/ReactiveUI/ReactiveCommand/ReactiveCommand.cs index 23ba5e57..45a6eb07 100644 --- a/src/ReactiveUI/ReactiveCommand/ReactiveCommand.cs +++ b/src/ReactiveUI/ReactiveCommand/ReactiveCommand.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Reactive; using System.Reactive.Concurrency; @@ -24,6 +25,7 @@ namespace ReactiveUI /// This non-generic base class defines the creation behavior of the ReactiveCommand's. /// /// + [SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:FileMayOnlyContainASingleType", Justification = "Same class just generic.")] public static class ReactiveCommand { /// @@ -535,6 +537,7 @@ namespace ReactiveUI /// /// The type of the values that are the result of command execution. /// + [SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:FileMayOnlyContainASingleType", Justification = "Same class just generic.")] public class ReactiveCommand : ReactiveCommandBase { private readonly Func> _execute; diff --git a/src/ReactiveUI/ReactiveCommand/ReactiveCommandBase.cs b/src/ReactiveUI/ReactiveCommand/ReactiveCommandBase.cs index 3f2a3075..bf0b0a52 100644 --- a/src/ReactiveUI/ReactiveCommand/ReactiveCommandBase.cs +++ b/src/ReactiveUI/ReactiveCommand/ReactiveCommandBase.cs @@ -82,7 +82,7 @@ namespace ReactiveUI } /// - /// An observable whose value indicates whether the command can currently execute. + /// Gets an observable whose value indicates whether the command can currently execute. /// /// /// The value provided by this observable is governed both by any canExecute observable provided during @@ -95,7 +95,7 @@ namespace ReactiveUI } /// - /// An observable whose value indicates whether the command is currently executing. + /// Gets an observable whose value indicates whether the command is currently executing. /// /// /// This observable can be particularly useful for updating UI, such as showing an activity indicator whilst a command @@ -107,7 +107,7 @@ namespace ReactiveUI } /// - /// An observable that ticks any exceptions in command execution logic. + /// Gets an observable that ticks any exceptions in command execution logic. /// /// /// Any exceptions that are not observed via this observable will propagate out and cause the application to be torn @@ -168,7 +168,7 @@ namespace ReactiveUI /// /// /// In those cases where execution fails, there will be no result value. Instead, the failure will tick through the - /// observable. + /// observable. /// /// /// diff --git a/src/ReactiveUI/ReactiveObject/ReactiveObject.cs b/src/ReactiveUI/ReactiveObject/ReactiveObject.cs index a2e8b270..0293a985 100644 --- a/src/ReactiveUI/ReactiveObject/ReactiveObject.cs +++ b/src/ReactiveUI/ReactiveObject/ReactiveObject.cs @@ -38,16 +38,11 @@ namespace ReactiveUI } #endif - /// - /// Represents an Observable that fires *before* a property is about to - /// be changed. - /// + /// [IgnoreDataMember] public IObservable> Changing => ((IReactiveObject)this).GetChangingObservable(); - /// - /// Represents an Observable that fires *after* a property has changed. - /// + /// [IgnoreDataMember] public IObservable> Changed => ((IReactiveObject)this).GetChangedObservable(); diff --git a/src/ReactiveUI/Routing/RoutingState.cs b/src/ReactiveUI/Routing/RoutingState.cs index 16d12bb9..cfb4691f 100644 --- a/src/ReactiveUI/Routing/RoutingState.cs +++ b/src/ReactiveUI/Routing/RoutingState.cs @@ -79,20 +79,20 @@ namespace ReactiveUI } /// - /// Gets or sets a observable which will navigate back to the previous element in the stack. + /// Gets or sets a command which will navigate back to the previous element in the stack. /// [IgnoreDataMember] public ReactiveCommand NavigateBack { get; protected set; } /// - /// Navigates to the a new element in the stack - the Execute parameter + /// Gets or sets a comamnd that navigates to the a new element in the stack - the Execute parameter /// must be a ViewModel that implements IRoutableViewModel. /// [IgnoreDataMember] public ReactiveCommand Navigate { get; protected set; } /// - /// Navigates to a new element and resets the navigation stack (i.e. the + /// Gets or sets a command that navigates to a new element and resets the navigation stack (i.e. the /// new ViewModel will now be the only element in the stack) - the /// Execute parameter must be a ViewModel that implements /// IRoutableViewModel. @@ -101,13 +101,13 @@ namespace ReactiveUI public ReactiveCommand NavigateAndReset { get; protected set; } /// - /// Gets the current view model which is to be shown for the Routing. + /// Gets or sets the current view model which is to be shown for the Routing. /// [IgnoreDataMember] public IObservable CurrentViewModel { get; protected set; } /// - /// Gets a Observable which will trigger when the Navigation changes. + /// Gets or sets an observable which will signal when the Navigation changes. /// [IgnoreDataMember] public IObservable> NavigationChanged { get; protected set; } diff --git a/src/ReactiveUI/RxApp.cs b/src/ReactiveUI/RxApp.cs index 596f729a..5b94323c 100644 --- a/src/ReactiveUI/RxApp.cs +++ b/src/ReactiveUI/RxApp.cs @@ -139,7 +139,7 @@ namespace ReactiveUI } /// - /// MainThreadScheduler is the scheduler used to schedule work items that + /// Gets or sets a scheduler used to schedule work items that /// should be run "on the UI thread". In normal mode, this will be /// DispatcherScheduler, and in Unit Test mode this will be Immediate, /// to simplify writing common unit tests. @@ -167,7 +167,7 @@ namespace ReactiveUI } /// - /// TaskpoolScheduler is the scheduler used to schedule work items to + /// Gets or sets the a the scheduler used to schedule work items to /// run in a background thread. In both modes, this will run on the TPL /// Task Pool. /// @@ -189,7 +189,7 @@ namespace ReactiveUI } /// - /// This Observer is signalled whenever an object that has a + /// Gets or sets the Observer which signalled whenever an object that has a /// ThrownExceptions property doesn't Subscribe to that Observable. Use /// Observer.Create to set up what will happen - the default is to crash /// the application with an error message. @@ -201,7 +201,7 @@ namespace ReactiveUI } /// - /// This returns / allows you to override the current SuspensionHost, a + /// Gets or sets the current SuspensionHost, a /// class which provides events for process lifetime events, especially /// on mobile devices. /// @@ -228,7 +228,7 @@ namespace ReactiveUI } /// - /// Returns whether your UI framework is brain-dead or not and will blow + /// Gets or sets a value indicating whether your UI framework is brain-dead or not and will blow /// up if a INotifyCollectionChanged object returns a ranged Add. /// public static bool SupportsRangeNotifications diff --git a/src/ReactiveUI/View/DefaultViewLocator.cs b/src/ReactiveUI/View/DefaultViewLocator.cs index c2bb884f..49eed7a0 100644 --- a/src/ReactiveUI/View/DefaultViewLocator.cs +++ b/src/ReactiveUI/View/DefaultViewLocator.cs @@ -1,4 +1,5 @@ using System; +using System.Diagnostics.CodeAnalysis; using System.Reflection; using Splat; @@ -6,6 +7,11 @@ namespace ReactiveUI { internal sealed class DefaultViewLocator : IViewLocator, IEnableLogger { + /// + /// Initializes a new instance of the class. + /// + /// The method which will convert a ViewModel name into a View. + [SuppressMessage("Globalization", "CA1307: operator could change based on locale settings", Justification = "Replace() does not have third parameter on all platforms")] public DefaultViewLocator(Func viewModelToViewFunc = null) { ViewModelToViewFunc = viewModelToViewFunc ?? (vm => vm.Replace("ViewModel", "View")); diff --git a/src/reactiveui.ruleset b/src/reactiveui.ruleset index 5c269d4c..64b6da29 100644 --- a/src/reactiveui.ruleset +++ b/src/reactiveui.ruleset @@ -11,68 +11,69 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -84,13 +85,13 @@ - - - - - - - + + + + + + + @@ -98,25 +99,28 @@ - - - - + + + + + - + + - + + @@ -125,13 +129,13 @@ - - + + - + - \ No newline at end of file + diff --git a/src/reactiveui.tests.ruleset b/src/reactiveui.tests.ruleset index dbf9641e..c42f159c 100644 --- a/src/reactiveui.tests.ruleset +++ b/src/reactiveui.tests.ruleset @@ -11,133 +11,141 @@ - - - - - - - - - + + + + + + + + + + + + + - - - - - - - - + + + + + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - + + - - - - - - - - - - - - - - + + + + + + + + + + + + + - - - + + + + + - - - - - + + + + + + + + + + + - - - - - - + - + - - + + + - - + + + + + + + + - - - - - - - + + + - \ No newline at end of file +