From f3e21ded129baf32f2846934614d74a0c6cab48d Mon Sep 17 00:00:00 2001 From: Glenn Watson Date: Thu, 23 Nov 2023 11:33:34 +1100 Subject: [PATCH] Revert "breaking change: Make Bind use non-generic IViewFor (#3676)" This reverts commit 246e8ef1ca47bff88228e33a1897aa966f6de109. --- ...valTests.ReactiveUI.DotNet6_0.verified.txt | 20 --- ...valTests.ReactiveUI.DotNet7_0.verified.txt | 20 --- ...valTests.ReactiveUI.DotNet8_0.verified.txt | 20 --- ...provalTests.ReactiveUI.Net4_7.verified.txt | 20 --- ...rovalTests.Winforms.DotNet6_0.verified.txt | 5 - ...rovalTests.Winforms.DotNet7_0.verified.txt | 5 - ...rovalTests.Winforms.DotNet8_0.verified.txt | 5 - ...ApprovalTests.Winforms.Net4_7.verified.txt | 5 - .../ReactiveUserControlNonGeneric.Designer.cs | 23 ---- .../ReactiveUserControlNonGeneric.cs | 39 ------ .../Bindings/Command/CommandBinder.cs | 112 ----------------- .../Command/CommandBinderImplementation.cs | 119 ------------------ .../CommandBinderImplementationMixins.cs | 37 +----- .../Bindings/Command/CreatesCommandBinding.cs | 30 ++++- .../Command/CreatesCommandBindingViaEvent.cs | 8 +- .../Command/ICommandBinderImplementation.cs | 54 +------- 16 files changed, 35 insertions(+), 487 deletions(-) delete mode 100644 src/ReactiveUI.Winforms/ReactiveUserControlNonGeneric.Designer.cs delete mode 100644 src/ReactiveUI.Winforms/ReactiveUserControlNonGeneric.cs diff --git a/src/ReactiveUI.Tests/API/ApiApprovalTests.ReactiveUI.DotNet6_0.verified.txt b/src/ReactiveUI.Tests/API/ApiApprovalTests.ReactiveUI.DotNet6_0.verified.txt index 428d21b6ba..72ceb2ac70 100644 --- a/src/ReactiveUI.Tests/API/ApiApprovalTests.ReactiveUI.DotNet6_0.verified.txt +++ b/src/ReactiveUI.Tests/API/ApiApprovalTests.ReactiveUI.DotNet6_0.verified.txt @@ -92,18 +92,6 @@ namespace ReactiveUI where TView : class, ReactiveUI.IViewFor where TViewModel : class where TProp : System.Windows.Input.ICommand { } - public static ReactiveUI.IReactiveBinding BindCommandNonGeneric(this TView view, TViewModel? viewModel, System.Linq.Expressions.Expression> propertyName, System.Linq.Expressions.Expression> controlName, string? toEvent = null) - where TView : class, ReactiveUI.IViewFor - where TViewModel : class - where TProp : System.Windows.Input.ICommand { } - public static ReactiveUI.IReactiveBinding BindCommandNonGeneric(this TView view, TViewModel? viewModel, System.Linq.Expressions.Expression> propertyName, System.Linq.Expressions.Expression> controlName, System.IObservable withParameter, string? toEvent = null) - where TView : class, ReactiveUI.IViewFor - where TViewModel : class - where TProp : System.Windows.Input.ICommand { } - public static ReactiveUI.IReactiveBinding BindCommandNonGeneric(this TView view, TViewModel? viewModel, System.Linq.Expressions.Expression> propertyName, System.Linq.Expressions.Expression> controlName, System.Linq.Expressions.Expression> withParameter, string? toEvent = null) - where TView : class, ReactiveUI.IViewFor - where TViewModel : class - where TProp : System.Windows.Input.ICommand { } } public class CommandBinderImplementation : Splat.IEnableLogger { @@ -116,14 +104,6 @@ namespace ReactiveUI where TView : class, ReactiveUI.IViewFor where TViewModel : class where TProp : System.Windows.Input.ICommand { } - public ReactiveUI.IReactiveBinding BindCommandNonGeneric(TViewModel? viewModel, TView view, System.Linq.Expressions.Expression> vmProperty, System.Linq.Expressions.Expression> controlProperty, System.IObservable withParameter, string? toEvent = null) - where TView : class, ReactiveUI.IViewFor - where TViewModel : class - where TProp : System.Windows.Input.ICommand { } - public ReactiveUI.IReactiveBinding BindCommandNonGeneric(TViewModel? viewModel, TView view, System.Linq.Expressions.Expression> vmProperty, System.Linq.Expressions.Expression> controlProperty, System.Linq.Expressions.Expression> withParameter, string? toEvent = null) - where TView : class, ReactiveUI.IViewFor - where TViewModel : class - where TProp : System.Windows.Input.ICommand { } } public static class ComparerChainingExtensions { diff --git a/src/ReactiveUI.Tests/API/ApiApprovalTests.ReactiveUI.DotNet7_0.verified.txt b/src/ReactiveUI.Tests/API/ApiApprovalTests.ReactiveUI.DotNet7_0.verified.txt index a0cc917fca..7ba5eb2379 100644 --- a/src/ReactiveUI.Tests/API/ApiApprovalTests.ReactiveUI.DotNet7_0.verified.txt +++ b/src/ReactiveUI.Tests/API/ApiApprovalTests.ReactiveUI.DotNet7_0.verified.txt @@ -92,18 +92,6 @@ namespace ReactiveUI where TView : class, ReactiveUI.IViewFor where TViewModel : class where TProp : System.Windows.Input.ICommand { } - public static ReactiveUI.IReactiveBinding BindCommandNonGeneric(this TView view, TViewModel? viewModel, System.Linq.Expressions.Expression> propertyName, System.Linq.Expressions.Expression> controlName, string? toEvent = null) - where TView : class, ReactiveUI.IViewFor - where TViewModel : class - where TProp : System.Windows.Input.ICommand { } - public static ReactiveUI.IReactiveBinding BindCommandNonGeneric(this TView view, TViewModel? viewModel, System.Linq.Expressions.Expression> propertyName, System.Linq.Expressions.Expression> controlName, System.IObservable withParameter, string? toEvent = null) - where TView : class, ReactiveUI.IViewFor - where TViewModel : class - where TProp : System.Windows.Input.ICommand { } - public static ReactiveUI.IReactiveBinding BindCommandNonGeneric(this TView view, TViewModel? viewModel, System.Linq.Expressions.Expression> propertyName, System.Linq.Expressions.Expression> controlName, System.Linq.Expressions.Expression> withParameter, string? toEvent = null) - where TView : class, ReactiveUI.IViewFor - where TViewModel : class - where TProp : System.Windows.Input.ICommand { } } public class CommandBinderImplementation : Splat.IEnableLogger { @@ -116,14 +104,6 @@ namespace ReactiveUI where TView : class, ReactiveUI.IViewFor where TViewModel : class where TProp : System.Windows.Input.ICommand { } - public ReactiveUI.IReactiveBinding BindCommandNonGeneric(TViewModel? viewModel, TView view, System.Linq.Expressions.Expression> vmProperty, System.Linq.Expressions.Expression> controlProperty, System.IObservable withParameter, string? toEvent = null) - where TView : class, ReactiveUI.IViewFor - where TViewModel : class - where TProp : System.Windows.Input.ICommand { } - public ReactiveUI.IReactiveBinding BindCommandNonGeneric(TViewModel? viewModel, TView view, System.Linq.Expressions.Expression> vmProperty, System.Linq.Expressions.Expression> controlProperty, System.Linq.Expressions.Expression> withParameter, string? toEvent = null) - where TView : class, ReactiveUI.IViewFor - where TViewModel : class - where TProp : System.Windows.Input.ICommand { } } public static class ComparerChainingExtensions { diff --git a/src/ReactiveUI.Tests/API/ApiApprovalTests.ReactiveUI.DotNet8_0.verified.txt b/src/ReactiveUI.Tests/API/ApiApprovalTests.ReactiveUI.DotNet8_0.verified.txt index 88019adb36..5e64bd4d15 100644 --- a/src/ReactiveUI.Tests/API/ApiApprovalTests.ReactiveUI.DotNet8_0.verified.txt +++ b/src/ReactiveUI.Tests/API/ApiApprovalTests.ReactiveUI.DotNet8_0.verified.txt @@ -92,18 +92,6 @@ namespace ReactiveUI where TView : class, ReactiveUI.IViewFor where TViewModel : class where TProp : System.Windows.Input.ICommand { } - public static ReactiveUI.IReactiveBinding BindCommandNonGeneric(this TView view, TViewModel? viewModel, System.Linq.Expressions.Expression> propertyName, System.Linq.Expressions.Expression> controlName, string? toEvent = null) - where TView : class, ReactiveUI.IViewFor - where TViewModel : class - where TProp : System.Windows.Input.ICommand { } - public static ReactiveUI.IReactiveBinding BindCommandNonGeneric(this TView view, TViewModel? viewModel, System.Linq.Expressions.Expression> propertyName, System.Linq.Expressions.Expression> controlName, System.IObservable withParameter, string? toEvent = null) - where TView : class, ReactiveUI.IViewFor - where TViewModel : class - where TProp : System.Windows.Input.ICommand { } - public static ReactiveUI.IReactiveBinding BindCommandNonGeneric(this TView view, TViewModel? viewModel, System.Linq.Expressions.Expression> propertyName, System.Linq.Expressions.Expression> controlName, System.Linq.Expressions.Expression> withParameter, string? toEvent = null) - where TView : class, ReactiveUI.IViewFor - where TViewModel : class - where TProp : System.Windows.Input.ICommand { } } public class CommandBinderImplementation : Splat.IEnableLogger { @@ -116,14 +104,6 @@ namespace ReactiveUI where TView : class, ReactiveUI.IViewFor where TViewModel : class where TProp : System.Windows.Input.ICommand { } - public ReactiveUI.IReactiveBinding BindCommandNonGeneric(TViewModel? viewModel, TView view, System.Linq.Expressions.Expression> vmProperty, System.Linq.Expressions.Expression> controlProperty, System.IObservable withParameter, string? toEvent = null) - where TView : class, ReactiveUI.IViewFor - where TViewModel : class - where TProp : System.Windows.Input.ICommand { } - public ReactiveUI.IReactiveBinding BindCommandNonGeneric(TViewModel? viewModel, TView view, System.Linq.Expressions.Expression> vmProperty, System.Linq.Expressions.Expression> controlProperty, System.Linq.Expressions.Expression> withParameter, string? toEvent = null) - where TView : class, ReactiveUI.IViewFor - where TViewModel : class - where TProp : System.Windows.Input.ICommand { } } public static class ComparerChainingExtensions { diff --git a/src/ReactiveUI.Tests/API/ApiApprovalTests.ReactiveUI.Net4_7.verified.txt b/src/ReactiveUI.Tests/API/ApiApprovalTests.ReactiveUI.Net4_7.verified.txt index 2e8f3eef9a..8bf6d33d37 100644 --- a/src/ReactiveUI.Tests/API/ApiApprovalTests.ReactiveUI.Net4_7.verified.txt +++ b/src/ReactiveUI.Tests/API/ApiApprovalTests.ReactiveUI.Net4_7.verified.txt @@ -90,18 +90,6 @@ namespace ReactiveUI where TView : class, ReactiveUI.IViewFor where TViewModel : class where TProp : System.Windows.Input.ICommand { } - public static ReactiveUI.IReactiveBinding BindCommandNonGeneric(this TView view, TViewModel? viewModel, System.Linq.Expressions.Expression> propertyName, System.Linq.Expressions.Expression> controlName, string? toEvent = null) - where TView : class, ReactiveUI.IViewFor - where TViewModel : class - where TProp : System.Windows.Input.ICommand { } - public static ReactiveUI.IReactiveBinding BindCommandNonGeneric(this TView view, TViewModel? viewModel, System.Linq.Expressions.Expression> propertyName, System.Linq.Expressions.Expression> controlName, System.IObservable withParameter, string? toEvent = null) - where TView : class, ReactiveUI.IViewFor - where TViewModel : class - where TProp : System.Windows.Input.ICommand { } - public static ReactiveUI.IReactiveBinding BindCommandNonGeneric(this TView view, TViewModel? viewModel, System.Linq.Expressions.Expression> propertyName, System.Linq.Expressions.Expression> controlName, System.Linq.Expressions.Expression> withParameter, string? toEvent = null) - where TView : class, ReactiveUI.IViewFor - where TViewModel : class - where TProp : System.Windows.Input.ICommand { } } public class CommandBinderImplementation : Splat.IEnableLogger { @@ -114,14 +102,6 @@ namespace ReactiveUI where TView : class, ReactiveUI.IViewFor where TViewModel : class where TProp : System.Windows.Input.ICommand { } - public ReactiveUI.IReactiveBinding BindCommandNonGeneric(TViewModel? viewModel, TView view, System.Linq.Expressions.Expression> vmProperty, System.Linq.Expressions.Expression> controlProperty, System.IObservable withParameter, string? toEvent = null) - where TView : class, ReactiveUI.IViewFor - where TViewModel : class - where TProp : System.Windows.Input.ICommand { } - public ReactiveUI.IReactiveBinding BindCommandNonGeneric(TViewModel? viewModel, TView view, System.Linq.Expressions.Expression> vmProperty, System.Linq.Expressions.Expression> controlProperty, System.Linq.Expressions.Expression> withParameter, string? toEvent = null) - where TView : class, ReactiveUI.IViewFor - where TViewModel : class - where TProp : System.Windows.Input.ICommand { } } public static class ComparerChainingExtensions { diff --git a/src/ReactiveUI.Tests/Platforms/winforms/API/WinformsApiApprovalTests.Winforms.DotNet6_0.verified.txt b/src/ReactiveUI.Tests/Platforms/winforms/API/WinformsApiApprovalTests.Winforms.DotNet6_0.verified.txt index 5d90003771..af951628a1 100644 --- a/src/ReactiveUI.Tests/Platforms/winforms/API/WinformsApiApprovalTests.Winforms.DotNet6_0.verified.txt +++ b/src/ReactiveUI.Tests/Platforms/winforms/API/WinformsApiApprovalTests.Winforms.DotNet6_0.verified.txt @@ -32,11 +32,6 @@ namespace ReactiveUI.Winforms public PlatformOperations() { } public string? GetOrientation() { } } - public class ReactiveUserControlNonGeneric : System.Windows.Forms.UserControl, ReactiveUI.IActivatableView, ReactiveUI.IViewFor - { - public ReactiveUserControlNonGeneric() { } - protected override void Dispose(bool disposing) { } - } public class ReactiveUserControl : System.Windows.Forms.UserControl, ReactiveUI.IActivatableView, ReactiveUI.IViewFor, ReactiveUI.IViewFor where TViewModel : class { diff --git a/src/ReactiveUI.Tests/Platforms/winforms/API/WinformsApiApprovalTests.Winforms.DotNet7_0.verified.txt b/src/ReactiveUI.Tests/Platforms/winforms/API/WinformsApiApprovalTests.Winforms.DotNet7_0.verified.txt index f8bac7dbb5..e576e83488 100644 --- a/src/ReactiveUI.Tests/Platforms/winforms/API/WinformsApiApprovalTests.Winforms.DotNet7_0.verified.txt +++ b/src/ReactiveUI.Tests/Platforms/winforms/API/WinformsApiApprovalTests.Winforms.DotNet7_0.verified.txt @@ -32,11 +32,6 @@ namespace ReactiveUI.Winforms public PlatformOperations() { } public string? GetOrientation() { } } - public class ReactiveUserControlNonGeneric : System.Windows.Forms.UserControl, ReactiveUI.IActivatableView, ReactiveUI.IViewFor - { - public ReactiveUserControlNonGeneric() { } - protected override void Dispose(bool disposing) { } - } public class ReactiveUserControl : System.Windows.Forms.UserControl, ReactiveUI.IActivatableView, ReactiveUI.IViewFor, ReactiveUI.IViewFor where TViewModel : class { diff --git a/src/ReactiveUI.Tests/Platforms/winforms/API/WinformsApiApprovalTests.Winforms.DotNet8_0.verified.txt b/src/ReactiveUI.Tests/Platforms/winforms/API/WinformsApiApprovalTests.Winforms.DotNet8_0.verified.txt index 32abdea373..ee964cd932 100644 --- a/src/ReactiveUI.Tests/Platforms/winforms/API/WinformsApiApprovalTests.Winforms.DotNet8_0.verified.txt +++ b/src/ReactiveUI.Tests/Platforms/winforms/API/WinformsApiApprovalTests.Winforms.DotNet8_0.verified.txt @@ -32,11 +32,6 @@ namespace ReactiveUI.Winforms public PlatformOperations() { } public string? GetOrientation() { } } - public class ReactiveUserControlNonGeneric : System.Windows.Forms.UserControl, ReactiveUI.IActivatableView, ReactiveUI.IViewFor - { - public ReactiveUserControlNonGeneric() { } - protected override void Dispose(bool disposing) { } - } public class ReactiveUserControl : System.Windows.Forms.UserControl, ReactiveUI.IActivatableView, ReactiveUI.IViewFor, ReactiveUI.IViewFor where TViewModel : class { diff --git a/src/ReactiveUI.Tests/Platforms/winforms/API/WinformsApiApprovalTests.Winforms.Net4_7.verified.txt b/src/ReactiveUI.Tests/Platforms/winforms/API/WinformsApiApprovalTests.Winforms.Net4_7.verified.txt index 3b64ac1766..92e5468102 100644 --- a/src/ReactiveUI.Tests/Platforms/winforms/API/WinformsApiApprovalTests.Winforms.Net4_7.verified.txt +++ b/src/ReactiveUI.Tests/Platforms/winforms/API/WinformsApiApprovalTests.Winforms.Net4_7.verified.txt @@ -30,11 +30,6 @@ namespace ReactiveUI.Winforms public PlatformOperations() { } public string? GetOrientation() { } } - public class ReactiveUserControlNonGeneric : System.Windows.Forms.UserControl, ReactiveUI.IActivatableView, ReactiveUI.IViewFor - { - public ReactiveUserControlNonGeneric() { } - protected override void Dispose(bool disposing) { } - } public class ReactiveUserControl : System.Windows.Forms.UserControl, ReactiveUI.IActivatableView, ReactiveUI.IViewFor, ReactiveUI.IViewFor where TViewModel : class { diff --git a/src/ReactiveUI.Winforms/ReactiveUserControlNonGeneric.Designer.cs b/src/ReactiveUI.Winforms/ReactiveUserControlNonGeneric.Designer.cs deleted file mode 100644 index 7648d0a303..0000000000 --- a/src/ReactiveUI.Winforms/ReactiveUserControlNonGeneric.Designer.cs +++ /dev/null @@ -1,23 +0,0 @@ -namespace ReactiveUI.Winforms; - -partial class ReactiveUserControlNonGeneric -{ - /// - /// Required designer variable. - /// - private System.ComponentModel.IContainer components = null; - - #region Component Designer generated code - - /// - /// Required method for Designer support - do not modify - /// the contents of this method with the code editor. - /// - private void InitializeComponent() - { - components = new System.ComponentModel.Container(); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - } - - #endregion -} diff --git a/src/ReactiveUI.Winforms/ReactiveUserControlNonGeneric.cs b/src/ReactiveUI.Winforms/ReactiveUserControlNonGeneric.cs deleted file mode 100644 index 0431b26499..0000000000 --- a/src/ReactiveUI.Winforms/ReactiveUserControlNonGeneric.cs +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright (c) 2023 .NET Foundation and Contributors. All rights reserved. -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for full license information. - -using System.Windows.Forms; - -namespace ReactiveUI.Winforms; - -/// -/// This is an UserControl that is both and UserControl and has a ReactiveObject powers -/// (i.e. you can call RaiseAndSetIfChanged). -/// -/// -/// -public partial class ReactiveUserControlNonGeneric : UserControl, IViewFor -{ - /// - /// Initializes a new instance of the class. - /// - public ReactiveUserControlNonGeneric() => InitializeComponent(); - - /// - object? IViewFor.ViewModel { get; set; } - - /// - /// Clean up any resources being used. - /// - /// true if managed resources should be disposed; otherwise, false. - protected override void Dispose(bool disposing) - { - if (disposing) - { - components?.Dispose(); - } - - base.Dispose(disposing); - } -} diff --git a/src/ReactiveUI/Bindings/Command/CommandBinder.cs b/src/ReactiveUI/Bindings/Command/CommandBinder.cs index 915eb084be..241e0c7145 100644 --- a/src/ReactiveUI/Bindings/Command/CommandBinder.cs +++ b/src/ReactiveUI/Bindings/Command/CommandBinder.cs @@ -55,39 +55,6 @@ static CommandBinder() where TProp : ICommand => _binderImplementation.BindCommand(viewModel, view, propertyName, controlName, withParameter, toEvent); - /// - /// Bind a command from the ViewModel to an explicitly specified control - /// on the View. - /// - /// The view type. - /// The view model type. - /// The property type. - /// The control type. - /// The parameter type. - /// A class representing the binding. Dispose it to disconnect - /// the binding. - /// The View. - /// The View model. - /// The ViewModel command to bind. - /// The name of the control on the view. - /// The ViewModel property to pass as the - /// param of the ICommand. - /// If specified, bind to the specific event - /// instead of the default. - /// NOTE: If this parameter is used inside WhenActivated, it's - /// important to dispose the binding when the view is deactivated. - public static IReactiveBinding BindCommandNonGeneric( - this TView view, - TViewModel? viewModel, - Expression> propertyName, - Expression> controlName, - IObservable withParameter, - string? toEvent = null) - where TView : class, IViewFor - where TViewModel : class - where TProp : ICommand => - _binderImplementation.BindCommandNonGeneric(viewModel, view, propertyName, controlName, withParameter, toEvent); - /// /// Bind a command from the ViewModel to an explicitly specified control /// on the View. @@ -117,35 +84,6 @@ static CommandBinder() where TProp : ICommand => _binderImplementation.BindCommand(viewModel, view, propertyName, controlName, toEvent); - /// - /// Bind a command from the ViewModel to an explicitly specified control - /// on the View. - /// - /// The view type. - /// The view model type. - /// The property type. - /// The control type. - /// A class representing the binding. Dispose it to disconnect - /// the binding. - /// The View. - /// The View model. - /// The ViewModel command to bind. - /// The name of the control on the view. - /// If specified, bind to the specific event - /// instead of the default. - /// NOTE: If this parameter is used inside WhenActivated, it's - /// important to dispose the binding when the view is deactivated. - public static IReactiveBinding BindCommandNonGeneric( - this TView view, - TViewModel? viewModel, - Expression> propertyName, - Expression> controlName, - string? toEvent = null) - where TView : class, IViewFor - where TViewModel : class - where TProp : ICommand => - _binderImplementation.BindCommandNonGeneric(viewModel, view, propertyName, controlName, toEvent); - /// /// Bind a command from the ViewModel to an explicitly specified control /// on the View. @@ -195,54 +133,4 @@ static CommandBinder() withParameter, toEvent); } - - /// - /// Bind a command from the ViewModel to an explicitly specified control - /// on the View. - /// - /// The view type. - /// The view model type. - /// The property type. - /// The control type. - /// The parameter type. - /// A class representing the binding. Dispose it to disconnect - /// the binding. - /// The View. - /// The View model. - /// The ViewModel command to bind. - /// The name of the control on the view. - /// The ViewModel property to pass as the - /// param of the ICommand. - /// If specified, bind to the specific event - /// instead of the default. - /// NOTE: If this parameter is used inside WhenActivated, it's - /// important to dispose the binding when the view is deactivated. - public static IReactiveBinding BindCommandNonGeneric( - this TView view, - TViewModel? viewModel, - Expression> propertyName, - Expression> controlName, - Expression> withParameter, - string? toEvent = null) - where TView : class, IViewFor - where TViewModel : class - where TProp : ICommand - { -#if NET6_0_OR_GREATER - ArgumentNullException.ThrowIfNull(view); -#else - if (view is null) - { - throw new ArgumentNullException(nameof(view)); - } -#endif - - return _binderImplementation.BindCommandNonGeneric( - viewModel, - view, - propertyName, - controlName, - withParameter, - toEvent); - } } diff --git a/src/ReactiveUI/Bindings/Command/CommandBinderImplementation.cs b/src/ReactiveUI/Bindings/Command/CommandBinderImplementation.cs index 64f1aec08f..2cf6e67b8d 100644 --- a/src/ReactiveUI/Bindings/Command/CommandBinderImplementation.cs +++ b/src/ReactiveUI/Bindings/Command/CommandBinderImplementation.cs @@ -74,68 +74,6 @@ public class CommandBinderImplementation : ICommandBinderImplementation bindingDisposable); } - /// - /// Bind a command from the ViewModel to an explicitly specified control - /// on the View. - /// - /// The view type. - /// The view model type. - /// The property type. - /// The control type. - /// The parameter type. - /// The View model. - /// The View. - /// The ViewModel command to bind. - /// The name of the control on the view. - /// The ViewModel property to pass as the - /// param of the ICommand. - /// If specified, bind to the specific event - /// instead of the default. - /// NOTE: If this parameter is used inside WhenActivated, it's - /// important to dispose the binding when the view is deactivated. - /// - /// A class representing the binding. Dispose it to disconnect - /// the binding. - /// - /// nameof(vmProperty) - /// or - /// nameof(vmProperty). - public IReactiveBinding BindCommandNonGeneric( - TViewModel? viewModel, - TView view, - Expression> vmProperty, - Expression> controlProperty, - Expression> withParameter, - string? toEvent = null) - where TView : class, IViewFor - where TViewModel : class - where TProp : ICommand - { - if (vmProperty is null) - { - throw new ArgumentNullException(nameof(vmProperty)); - } - - if (controlProperty is null) - { - throw new ArgumentNullException(nameof(controlProperty)); - } - - var vmExpression = Reflection.Rewrite(vmProperty.Body); - var controlExpression = Reflection.Rewrite(controlProperty.Body); - var source = Reflection.ViewModelWhenAnyValue(viewModel, view, vmExpression).Cast(); - - var bindingDisposable = BindCommandInternal(source, view, controlExpression, withParameter.ToObservable(viewModel), toEvent); - - return new ReactiveBinding( - view, - controlExpression, - vmExpression, - source, - BindingDirection.OneWay, - bindingDisposable); - } - /// /// Bind a command from the ViewModel to an explicitly specified control /// on the View. @@ -193,63 +131,6 @@ public class CommandBinderImplementation : ICommandBinderImplementation bindingDisposable); } - /// - /// Bind a command from the ViewModel to an explicitly specified control - /// on the View. - /// - /// The view type. - /// The view model type. - /// The property type. - /// The control type. - /// The parameter type. - /// A class representing the binding. Dispose it to disconnect - /// the binding. - /// The View model. - /// The View. - /// The ViewModel command to bind. - /// The name of the control on the view. - /// The ViewModel property to pass as the - /// param of the ICommand. - /// If specified, bind to the specific event - /// instead of the default. - /// NOTE: If this parameter is used inside WhenActivated, it's - /// important to dispose the binding when the view is deactivated. - public IReactiveBinding BindCommandNonGeneric( - TViewModel? viewModel, - TView view, - Expression> vmProperty, - Expression> controlProperty, - IObservable withParameter, - string? toEvent = null) - where TView : class, IViewFor - where TViewModel : class - where TProp : ICommand - { - if (vmProperty is null) - { - throw new ArgumentNullException(nameof(vmProperty)); - } - - if (controlProperty is null) - { - throw new ArgumentNullException(nameof(controlProperty)); - } - - var vmExpression = Reflection.Rewrite(vmProperty.Body); - var controlExpression = Reflection.Rewrite(controlProperty.Body); - var source = Reflection.ViewModelWhenAnyValue(viewModel, view, vmExpression).Cast(); - - var bindingDisposable = BindCommandInternal(source, view, controlExpression, withParameter, toEvent); - - return new ReactiveBinding( - view, - controlExpression, - vmExpression, - source, - BindingDirection.OneWay, - bindingDisposable); - } - private static IDisposable BindCommandInternal( IObservable source, TView view, diff --git a/src/ReactiveUI/Bindings/Command/CommandBinderImplementationMixins.cs b/src/ReactiveUI/Bindings/Command/CommandBinderImplementationMixins.cs index 1ad482159f..25a1e6b5d5 100644 --- a/src/ReactiveUI/Bindings/Command/CommandBinderImplementationMixins.cs +++ b/src/ReactiveUI/Bindings/Command/CommandBinderImplementationMixins.cs @@ -46,39 +46,4 @@ internal static class CommandBinderImplementationMixins return @this.BindCommand(viewModel, view, propertyName, controlName, param, toEvent); } - - public static IReactiveBinding BindCommandNonGeneric( - this ICommandBinderImplementation @this, - TViewModel? viewModel, - TView view, - Expression> propertyName, - Expression> controlName, - string? toEvent = null) - where TView : class, IViewFor - where TViewModel : class - where TProp : ICommand => - @this.BindCommandNonGeneric(viewModel, view, propertyName, controlName, Observable.Empty, toEvent); - - public static IReactiveBinding BindCommandNonGeneric( - this ICommandBinderImplementation @this, - TViewModel? viewModel, - TView view, - Expression> propertyName, - Expression> controlName, - Expression> withParameter, - string? toEvent = null) - where TView : class, IViewFor - where TViewModel : class - where TProp : ICommand - { - if (withParameter is null) - { - throw new ArgumentNullException(nameof(withParameter)); - } - - var paramExpression = Reflection.Rewrite(withParameter.Body); - var param = Reflection.ViewModelWhenAnyValue(viewModel, view, paramExpression); - - return @this.BindCommandNonGeneric(viewModel, view, propertyName, controlName, param, toEvent); - } -} +} \ No newline at end of file diff --git a/src/ReactiveUI/Bindings/Command/CreatesCommandBinding.cs b/src/ReactiveUI/Bindings/Command/CreatesCommandBinding.cs index 15f7cb04b8..33b2fe978d 100644 --- a/src/ReactiveUI/Bindings/Command/CreatesCommandBinding.cs +++ b/src/ReactiveUI/Bindings/Command/CreatesCommandBinding.cs @@ -35,20 +35,42 @@ internal class CreatesCommandBinding public static IDisposable BindCommandToObject(ICommand? command, object? target, IObservable commandParameter) { var type = target!.GetType(); - var binder = _bindCommandCache.Get(type) ?? throw new Exception($"Couldn't find a Command Binder for {type.FullName}"); - var ret = binder.BindCommandToObject(command, target, commandParameter) ?? throw new Exception($"Couldn't bind Command Binder for {type.FullName}"); + var binder = _bindCommandCache.Get(type); + if (binder is null) + { + throw new Exception($"Couldn't find a Command Binder for {type.FullName}"); + } + + var ret = binder.BindCommandToObject(command, target, commandParameter); + if (ret is null) + { + throw new Exception($"Couldn't bind Command Binder for {type.FullName}"); + } + return ret; } public static IDisposable BindCommandToObject(ICommand? command, object? target, IObservable commandParameter, string? eventName) { var type = target!.GetType(); - var binder = _bindCommandEventCache.Get(type) ?? throw new Exception($"Couldn't find an Event Binder for {type.FullName} and event {eventName}"); + var binder = _bindCommandEventCache.Get(type); + if (binder is null) + { + throw new Exception($"Couldn't find an Event Binder for {type.FullName} and event {eventName}"); + } + var eventArgsType = Reflection.GetEventArgsTypeForEvent(type, eventName); var mi = binder.GetType().GetTypeInfo().DeclaredMethods.First(x => x.Name == "BindCommandToObject" && x.IsGenericMethod); mi = mi.MakeGenericMethod(eventArgsType); - var ret = (IDisposable)mi.Invoke(binder, [command, target, commandParameter, eventName])! ?? throw new Exception($"Couldn't bind Command Binder for {type.FullName} and event {eventName}"); + var ret = (IDisposable)mi.Invoke(binder, [command, target, commandParameter, eventName])!; + + // If we made it this far then this will not fail. + if (ret is null) + { + throw new Exception($"Couldn't bind Command Binder for {type.FullName} and event {eventName}"); + } + return ret; } } diff --git a/src/ReactiveUI/Bindings/Command/CreatesCommandBindingViaEvent.cs b/src/ReactiveUI/Bindings/Command/CreatesCommandBindingViaEvent.cs index 9cbe49e38d..2b853c029d 100644 --- a/src/ReactiveUI/Bindings/Command/CreatesCommandBindingViaEvent.cs +++ b/src/ReactiveUI/Bindings/Command/CreatesCommandBindingViaEvent.cs @@ -55,8 +55,14 @@ public int GetAffinityForObject(Type type, bool hasEventTarget) var type = target.GetType(); var eventInfo = _defaultEventsToBind .Select(x => new { EventInfo = type.GetRuntimeEvent(x.name), Args = x.type }) - .FirstOrDefault(x => x.EventInfo is not null) ?? throw new Exception( + .FirstOrDefault(x => x.EventInfo is not null); + + if (eventInfo is null) + { + throw new Exception( $"Couldn't find a default event to bind to on {target.GetType().FullName}, specify an event explicitly"); + } + var mi = GetType().GetRuntimeMethods().First(x => x.Name == "BindCommandToObject" && x.IsGenericMethod); mi = mi.MakeGenericMethod(eventInfo.Args); diff --git a/src/ReactiveUI/Bindings/Command/ICommandBinderImplementation.cs b/src/ReactiveUI/Bindings/Command/ICommandBinderImplementation.cs index d309d10688..650c06eeb4 100644 --- a/src/ReactiveUI/Bindings/Command/ICommandBinderImplementation.cs +++ b/src/ReactiveUI/Bindings/Command/ICommandBinderImplementation.cs @@ -63,56 +63,4 @@ internal interface ICommandBinderImplementation : IEnableLogger where TView : class, IViewFor where TViewModel : class where TProp : ICommand; - - /// - /// Binds the command on a ViewModel to a control on the View. - /// - /// The view model to bind to. - /// The view to bind to. - /// The name of the property on the View Model. - /// The name of the control on the View. - /// A function if we want to pass a parameter to the ICommand. - /// A event on the view that will also trigger the command. - /// The type of the view. - /// The type of the view model. - /// The type of the property on the view model. - /// The type of control on the view. - /// The type of the parameter to pass to the ICommand. - /// A reactive binding. Often only used for disposing the binding. - IReactiveBinding BindCommandNonGeneric( - TViewModel? viewModel, - TView view, - Expression> vmProperty, - Expression> controlProperty, - Expression> withParameter, - string? toEvent = null) - where TView : class, IViewFor - where TViewModel : class - where TProp : ICommand; - - /// - /// Binds the command on a ViewModel to a control on the View. - /// - /// The view model to bind to. - /// The view to bind to. - /// The name of the property on the View Model. - /// The name of the control on the View. - /// A observable if we want to pass a parameter to the ICommand. - /// A event on the view that will also trigger the command. - /// The type of the view. - /// The type of the view model. - /// The type of the property on the view model. - /// The type of control on the view. - /// The type of the parameter to pass to the ICommand. - /// A reactive binding. Often only used for disposing the binding. - IReactiveBinding BindCommandNonGeneric( - TViewModel? viewModel, - TView view, - Expression> vmProperty, - Expression> controlProperty, - IObservable withParameter, - string? toEvent = null) - where TView : class, IViewFor - where TViewModel : class - where TProp : ICommand; -} +} \ No newline at end of file