Skip to content

Commit

Permalink
breaking change: Make Bind use non-generic IViewFor (#3676)
Browse files Browse the repository at this point in the history
<!-- Please be sure to read the
[Contribute](https://github.com/reactiveui/reactiveui#contribute)
section of the README -->

**What kind of change does this PR introduce?**
<!-- Bug fix, feature, docs update, ... -->

Fix for #3644

**What is the current behavior?**
<!-- You can also link to an open issue here. -->

BindCommand requires a view inherited from `IViewFor<TViewModel>`
ReactiveUserControl inherits `IViewFor<TViewModel>` which requires
Generics which WinForms does not work well with.

**What is the new behavior?**
<!-- If this is a feature change -->

Add BindCommandNonGeneric this is to avoid the request of not changing
the existing code, therefore adding to the available options.
NOTE: Bind only requires `IViewFor` and `IViewFor<TViewModel>` inherits
`IViewFor` therefore would still be an API change if BindCommand were
relaxed to IViewFor in the same way as Bind, but perhaps the best route.

add ReactiveUserControlNonGeneric for WinForms -  inherits `IViewFor`

**What might this PR break?**

Non due to new functions

**Please check if the PR fulfills these requirements**
- [ ] Tests for the changes have been added (for bug fixes / features)
- [ ] Docs have been added / updated (for bug fixes / features)

**Other information**:
  • Loading branch information
ChrisPulman committed Nov 23, 2023
1 parent 45a92af commit 246e8ef
Show file tree
Hide file tree
Showing 16 changed files with 487 additions and 35 deletions.
Expand Up @@ -92,6 +92,18 @@ namespace ReactiveUI
where TView : class, ReactiveUI.IViewFor<TViewModel>
where TViewModel : class
where TProp : System.Windows.Input.ICommand { }
public static ReactiveUI.IReactiveBinding<TView, TProp> BindCommandNonGeneric<TView, TViewModel, TProp, TControl>(this TView view, TViewModel? viewModel, System.Linq.Expressions.Expression<System.Func<TViewModel, TProp?>> propertyName, System.Linq.Expressions.Expression<System.Func<TView, TControl>> controlName, string? toEvent = null)
where TView : class, ReactiveUI.IViewFor
where TViewModel : class
where TProp : System.Windows.Input.ICommand { }
public static ReactiveUI.IReactiveBinding<TView, TProp> BindCommandNonGeneric<TView, TViewModel, TProp, TControl, TParam>(this TView view, TViewModel? viewModel, System.Linq.Expressions.Expression<System.Func<TViewModel, TProp?>> propertyName, System.Linq.Expressions.Expression<System.Func<TView, TControl>> controlName, System.IObservable<TParam?> withParameter, string? toEvent = null)
where TView : class, ReactiveUI.IViewFor
where TViewModel : class
where TProp : System.Windows.Input.ICommand { }
public static ReactiveUI.IReactiveBinding<TView, TProp> BindCommandNonGeneric<TView, TViewModel, TProp, TControl, TParam>(this TView view, TViewModel? viewModel, System.Linq.Expressions.Expression<System.Func<TViewModel, TProp?>> propertyName, System.Linq.Expressions.Expression<System.Func<TView, TControl>> controlName, System.Linq.Expressions.Expression<System.Func<TViewModel, TParam?>> withParameter, string? toEvent = null)
where TView : class, ReactiveUI.IViewFor
where TViewModel : class
where TProp : System.Windows.Input.ICommand { }
}
public class CommandBinderImplementation : Splat.IEnableLogger
{
Expand All @@ -104,6 +116,14 @@ namespace ReactiveUI
where TView : class, ReactiveUI.IViewFor<TViewModel>
where TViewModel : class
where TProp : System.Windows.Input.ICommand { }
public ReactiveUI.IReactiveBinding<TView, TProp> BindCommandNonGeneric<TView, TViewModel, TProp, TControl, TParam>(TViewModel? viewModel, TView view, System.Linq.Expressions.Expression<System.Func<TViewModel, TProp?>> vmProperty, System.Linq.Expressions.Expression<System.Func<TView, TControl>> controlProperty, System.IObservable<TParam?> withParameter, string? toEvent = null)
where TView : class, ReactiveUI.IViewFor
where TViewModel : class
where TProp : System.Windows.Input.ICommand { }
public ReactiveUI.IReactiveBinding<TView, TProp> BindCommandNonGeneric<TView, TViewModel, TProp, TControl, TParam>(TViewModel? viewModel, TView view, System.Linq.Expressions.Expression<System.Func<TViewModel, TProp?>> vmProperty, System.Linq.Expressions.Expression<System.Func<TView, TControl>> controlProperty, System.Linq.Expressions.Expression<System.Func<TViewModel, TParam?>> withParameter, string? toEvent = null)
where TView : class, ReactiveUI.IViewFor
where TViewModel : class
where TProp : System.Windows.Input.ICommand { }
}
public static class ComparerChainingExtensions
{
Expand Down
Expand Up @@ -92,6 +92,18 @@ namespace ReactiveUI
where TView : class, ReactiveUI.IViewFor<TViewModel>
where TViewModel : class
where TProp : System.Windows.Input.ICommand { }
public static ReactiveUI.IReactiveBinding<TView, TProp> BindCommandNonGeneric<TView, TViewModel, TProp, TControl>(this TView view, TViewModel? viewModel, System.Linq.Expressions.Expression<System.Func<TViewModel, TProp?>> propertyName, System.Linq.Expressions.Expression<System.Func<TView, TControl>> controlName, string? toEvent = null)
where TView : class, ReactiveUI.IViewFor
where TViewModel : class
where TProp : System.Windows.Input.ICommand { }
public static ReactiveUI.IReactiveBinding<TView, TProp> BindCommandNonGeneric<TView, TViewModel, TProp, TControl, TParam>(this TView view, TViewModel? viewModel, System.Linq.Expressions.Expression<System.Func<TViewModel, TProp?>> propertyName, System.Linq.Expressions.Expression<System.Func<TView, TControl>> controlName, System.IObservable<TParam?> withParameter, string? toEvent = null)
where TView : class, ReactiveUI.IViewFor
where TViewModel : class
where TProp : System.Windows.Input.ICommand { }
public static ReactiveUI.IReactiveBinding<TView, TProp> BindCommandNonGeneric<TView, TViewModel, TProp, TControl, TParam>(this TView view, TViewModel? viewModel, System.Linq.Expressions.Expression<System.Func<TViewModel, TProp?>> propertyName, System.Linq.Expressions.Expression<System.Func<TView, TControl>> controlName, System.Linq.Expressions.Expression<System.Func<TViewModel, TParam?>> withParameter, string? toEvent = null)
where TView : class, ReactiveUI.IViewFor
where TViewModel : class
where TProp : System.Windows.Input.ICommand { }
}
public class CommandBinderImplementation : Splat.IEnableLogger
{
Expand All @@ -104,6 +116,14 @@ namespace ReactiveUI
where TView : class, ReactiveUI.IViewFor<TViewModel>
where TViewModel : class
where TProp : System.Windows.Input.ICommand { }
public ReactiveUI.IReactiveBinding<TView, TProp> BindCommandNonGeneric<TView, TViewModel, TProp, TControl, TParam>(TViewModel? viewModel, TView view, System.Linq.Expressions.Expression<System.Func<TViewModel, TProp?>> vmProperty, System.Linq.Expressions.Expression<System.Func<TView, TControl>> controlProperty, System.IObservable<TParam?> withParameter, string? toEvent = null)
where TView : class, ReactiveUI.IViewFor
where TViewModel : class
where TProp : System.Windows.Input.ICommand { }
public ReactiveUI.IReactiveBinding<TView, TProp> BindCommandNonGeneric<TView, TViewModel, TProp, TControl, TParam>(TViewModel? viewModel, TView view, System.Linq.Expressions.Expression<System.Func<TViewModel, TProp?>> vmProperty, System.Linq.Expressions.Expression<System.Func<TView, TControl>> controlProperty, System.Linq.Expressions.Expression<System.Func<TViewModel, TParam?>> withParameter, string? toEvent = null)
where TView : class, ReactiveUI.IViewFor
where TViewModel : class
where TProp : System.Windows.Input.ICommand { }
}
public static class ComparerChainingExtensions
{
Expand Down
Expand Up @@ -92,6 +92,18 @@ namespace ReactiveUI
where TView : class, ReactiveUI.IViewFor<TViewModel>
where TViewModel : class
where TProp : System.Windows.Input.ICommand { }
public static ReactiveUI.IReactiveBinding<TView, TProp> BindCommandNonGeneric<TView, TViewModel, TProp, TControl>(this TView view, TViewModel? viewModel, System.Linq.Expressions.Expression<System.Func<TViewModel, TProp?>> propertyName, System.Linq.Expressions.Expression<System.Func<TView, TControl>> controlName, string? toEvent = null)
where TView : class, ReactiveUI.IViewFor
where TViewModel : class
where TProp : System.Windows.Input.ICommand { }
public static ReactiveUI.IReactiveBinding<TView, TProp> BindCommandNonGeneric<TView, TViewModel, TProp, TControl, TParam>(this TView view, TViewModel? viewModel, System.Linq.Expressions.Expression<System.Func<TViewModel, TProp?>> propertyName, System.Linq.Expressions.Expression<System.Func<TView, TControl>> controlName, System.IObservable<TParam?> withParameter, string? toEvent = null)
where TView : class, ReactiveUI.IViewFor
where TViewModel : class
where TProp : System.Windows.Input.ICommand { }
public static ReactiveUI.IReactiveBinding<TView, TProp> BindCommandNonGeneric<TView, TViewModel, TProp, TControl, TParam>(this TView view, TViewModel? viewModel, System.Linq.Expressions.Expression<System.Func<TViewModel, TProp?>> propertyName, System.Linq.Expressions.Expression<System.Func<TView, TControl>> controlName, System.Linq.Expressions.Expression<System.Func<TViewModel, TParam?>> withParameter, string? toEvent = null)
where TView : class, ReactiveUI.IViewFor
where TViewModel : class
where TProp : System.Windows.Input.ICommand { }
}
public class CommandBinderImplementation : Splat.IEnableLogger
{
Expand All @@ -104,6 +116,14 @@ namespace ReactiveUI
where TView : class, ReactiveUI.IViewFor<TViewModel>
where TViewModel : class
where TProp : System.Windows.Input.ICommand { }
public ReactiveUI.IReactiveBinding<TView, TProp> BindCommandNonGeneric<TView, TViewModel, TProp, TControl, TParam>(TViewModel? viewModel, TView view, System.Linq.Expressions.Expression<System.Func<TViewModel, TProp?>> vmProperty, System.Linq.Expressions.Expression<System.Func<TView, TControl>> controlProperty, System.IObservable<TParam?> withParameter, string? toEvent = null)
where TView : class, ReactiveUI.IViewFor
where TViewModel : class
where TProp : System.Windows.Input.ICommand { }
public ReactiveUI.IReactiveBinding<TView, TProp> BindCommandNonGeneric<TView, TViewModel, TProp, TControl, TParam>(TViewModel? viewModel, TView view, System.Linq.Expressions.Expression<System.Func<TViewModel, TProp?>> vmProperty, System.Linq.Expressions.Expression<System.Func<TView, TControl>> controlProperty, System.Linq.Expressions.Expression<System.Func<TViewModel, TParam?>> withParameter, string? toEvent = null)
where TView : class, ReactiveUI.IViewFor
where TViewModel : class
where TProp : System.Windows.Input.ICommand { }
}
public static class ComparerChainingExtensions
{
Expand Down
Expand Up @@ -90,6 +90,18 @@ namespace ReactiveUI
where TView : class, ReactiveUI.IViewFor<TViewModel>
where TViewModel : class
where TProp : System.Windows.Input.ICommand { }
public static ReactiveUI.IReactiveBinding<TView, TProp> BindCommandNonGeneric<TView, TViewModel, TProp, TControl>(this TView view, TViewModel? viewModel, System.Linq.Expressions.Expression<System.Func<TViewModel, TProp?>> propertyName, System.Linq.Expressions.Expression<System.Func<TView, TControl>> controlName, string? toEvent = null)
where TView : class, ReactiveUI.IViewFor
where TViewModel : class
where TProp : System.Windows.Input.ICommand { }
public static ReactiveUI.IReactiveBinding<TView, TProp> BindCommandNonGeneric<TView, TViewModel, TProp, TControl, TParam>(this TView view, TViewModel? viewModel, System.Linq.Expressions.Expression<System.Func<TViewModel, TProp?>> propertyName, System.Linq.Expressions.Expression<System.Func<TView, TControl>> controlName, System.IObservable<TParam?> withParameter, string? toEvent = null)
where TView : class, ReactiveUI.IViewFor
where TViewModel : class
where TProp : System.Windows.Input.ICommand { }
public static ReactiveUI.IReactiveBinding<TView, TProp> BindCommandNonGeneric<TView, TViewModel, TProp, TControl, TParam>(this TView view, TViewModel? viewModel, System.Linq.Expressions.Expression<System.Func<TViewModel, TProp?>> propertyName, System.Linq.Expressions.Expression<System.Func<TView, TControl>> controlName, System.Linq.Expressions.Expression<System.Func<TViewModel, TParam?>> withParameter, string? toEvent = null)
where TView : class, ReactiveUI.IViewFor
where TViewModel : class
where TProp : System.Windows.Input.ICommand { }
}
public class CommandBinderImplementation : Splat.IEnableLogger
{
Expand All @@ -102,6 +114,14 @@ namespace ReactiveUI
where TView : class, ReactiveUI.IViewFor<TViewModel>
where TViewModel : class
where TProp : System.Windows.Input.ICommand { }
public ReactiveUI.IReactiveBinding<TView, TProp> BindCommandNonGeneric<TView, TViewModel, TProp, TControl, TParam>(TViewModel? viewModel, TView view, System.Linq.Expressions.Expression<System.Func<TViewModel, TProp?>> vmProperty, System.Linq.Expressions.Expression<System.Func<TView, TControl>> controlProperty, System.IObservable<TParam?> withParameter, string? toEvent = null)
where TView : class, ReactiveUI.IViewFor
where TViewModel : class
where TProp : System.Windows.Input.ICommand { }
public ReactiveUI.IReactiveBinding<TView, TProp> BindCommandNonGeneric<TView, TViewModel, TProp, TControl, TParam>(TViewModel? viewModel, TView view, System.Linq.Expressions.Expression<System.Func<TViewModel, TProp?>> vmProperty, System.Linq.Expressions.Expression<System.Func<TView, TControl>> controlProperty, System.Linq.Expressions.Expression<System.Func<TViewModel, TParam?>> withParameter, string? toEvent = null)
where TView : class, ReactiveUI.IViewFor
where TViewModel : class
where TProp : System.Windows.Input.ICommand { }
}
public static class ComparerChainingExtensions
{
Expand Down
Expand Up @@ -32,6 +32,11 @@ 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<TViewModel> : System.Windows.Forms.UserControl, ReactiveUI.IActivatableView, ReactiveUI.IViewFor, ReactiveUI.IViewFor<TViewModel>
where TViewModel : class
{
Expand Down
Expand Up @@ -32,6 +32,11 @@ 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<TViewModel> : System.Windows.Forms.UserControl, ReactiveUI.IActivatableView, ReactiveUI.IViewFor, ReactiveUI.IViewFor<TViewModel>
where TViewModel : class
{
Expand Down
Expand Up @@ -32,6 +32,11 @@ 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<TViewModel> : System.Windows.Forms.UserControl, ReactiveUI.IActivatableView, ReactiveUI.IViewFor, ReactiveUI.IViewFor<TViewModel>
where TViewModel : class
{
Expand Down
Expand Up @@ -30,6 +30,11 @@ 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<TViewModel> : System.Windows.Forms.UserControl, ReactiveUI.IActivatableView, ReactiveUI.IViewFor, ReactiveUI.IViewFor<TViewModel>
where TViewModel : class
{
Expand Down
23 changes: 23 additions & 0 deletions src/ReactiveUI.Winforms/ReactiveUserControlNonGeneric.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

39 changes: 39 additions & 0 deletions src/ReactiveUI.Winforms/ReactiveUserControlNonGeneric.cs
@@ -0,0 +1,39 @@
// 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;

/// <summary>
/// This is an UserControl that is both and UserControl and has a ReactiveObject powers
/// (i.e. you can call RaiseAndSetIfChanged).
/// </summary>
/// <seealso cref="System.Windows.Forms.UserControl" />
/// <seealso cref="ReactiveUI.IViewFor" />
public partial class ReactiveUserControlNonGeneric : UserControl, IViewFor
{
/// <summary>
/// Initializes a new instance of the <see cref="ReactiveUserControlNonGeneric"/> class.
/// </summary>
public ReactiveUserControlNonGeneric() => InitializeComponent();

/// <inheritdoc/>
object? IViewFor.ViewModel { get; set; }

/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing)
{
components?.Dispose();
}

base.Dispose(disposing);
}
}

0 comments on commit 246e8ef

Please sign in to comment.