-
-
Notifications
You must be signed in to change notification settings - Fork 3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Source Generators for specialized ReactiveUI controls (Winforms, WPF, etc) #35
Comments
https://github.com/reactiveui/ReactiveUI.SourceGenerators?tab=readme-ov-file#usage-iviewfor-iviewfornameofviewmodelname
|
No, that's a helper to implement IViewFor interface (and it's pretty good). I'm talking about specific controls that exists in ReactiveUI.Winforms NuGet like this: https://github.com/reactiveui/ReactiveUI/blob/main/src/ReactiveUI.Winforms/ReactiveUserControl.cs Those controls are used as base classes, and they force it's parent as (in this case) UserControl base class:
|
Technically the [IViewFor(nameof(MyViewModel))] Attribute will do exactly what you are wishing, it hasn't yet been released but we are working on getting our release mechanism ready to produce a release using ReactiveUI.SourceGenerators;
namespace MyApp.WinForms;
[IViewFor(nameof(MyViewModel))]
public partial class MyReactiveUserControl : MyBaseUserControl
{
/// <summary>
/// Initializes a new instance of the <see cref="MyReactiveUserControl "/> class.
/// </summary>
public MyReactiveUserControl()
{
InitializeComponent();
ViewModel = new MyViewModel();
}
} This will produce the following additional code which should maintain compatibility with the WinForms Designer. using ReactiveUI;
using System.ComponentModel;
// <auto-generated/>
#pragma warning disable
#nullable enable
namespace MyApp.WinForms
{
[global::System.CodeDom.Compiler.GeneratedCode("ReactiveUI.SourceGenerators.IViewForGenerator", "1.1.0.0")]
public partial class MyReactiveUserControl : IViewFor<MyViewModel>
{
/// <inheritdoc/>
[Category("ReactiveUI")]
[Description("The ViewModel.")]
[Bindable(true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public MyViewModel? ViewModel { get; set; }
/// <inheritdoc/>
object? IViewFor.ViewModel { get => ViewModel; set => ViewModel = (MyViewModel? )value; }
}
}
#nullable restore
#pragma warning restore |
Well, in the case of ReactiveUserControl, this could be the replacement. But there are other specialized controls, like RoutedControlHost or ViewModelControlHost that are more than that: https://github.com/reactiveui/ReactiveUI/blob/main/src/ReactiveUI.Winforms/RoutedViewHost.cs https://github.com/reactiveui/ReactiveUI/blob/main/src/ReactiveUI.Winforms/ViewModelViewHost.cs Those controls are the ones that currently could improve if we could change which base class is using (for example, instead of UserControl, use XtraUserControl). Do you think is a bad idea?
|
Okay this is a valid idea, I will try to put something together in the next few days to cover these too. All platforms could benefit from this too. |
Great to hear that! I was thinking it would require an specialized version of IViewFor attribute but implementing only the generic part of IViewFor, not the non-generic part, because the non-generic part would be on those controls and the property implementation would use the base ViewModel property from ReactiveUI specialized control. Something like this: using ReactiveUI;
using System.ComponentModel;
// <auto-generated/>
#pragma warning disable
#nullable enable
namespace MyApp.WinForms
{
[global::System.CodeDom.Compiler.GeneratedCode("ReactiveUI.SourceGenerators.IViewForGenerator", "1.1.0.0")]
public partial class MyReactiveUserControl : IViewFor<MyViewModel>
{
/// <inheritdoc/>
[Category("ReactiveUI")]
[Description("The ViewModel.")]
[Bindable(true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public MyViewModel? ViewModel { get => (MyViewModel?)base.ViewModel; set => base.ViewModel = value; }
}
}
#nullable restore
#pragma warning restore |
Won't be better to separate those specialized WinForms controls in a separate Nuget? Like ReactiveUI.SourceGenerators.WinForms. So each platform could have it's specialized nuget (Wpf, etc). They can require the "Core" one so everything is integrated. |
As the code is generated in your project and you get no reference to the Source Generators in your final assembly I don't see the benefits of having separated packages, opted for the namespace difference to identify the functionality is for a particular platform. |
V1.1.26 has been released, please try the WinForms Generators included |
Ok, after testing it's a great solution but I think it can be easier if it wouldn't require to pass as argument the base type. Base type can be applied directly in the "master class" as this: [RoutedControlHost]
public partial class TestWinFormsRCHost : XtraUserControl
{
} What do you think? |
I'm working with ReactiveUI in a WinForms app with DevExpress but I'm having a hard time because ReactiveUI winforms controls (ReactiveUserControl, RoutedControlHost, RoutedControlHost , etc) inherits directly from UserControl, and because i'm working with DevExpress, I'm losing DevExpress benefits like Skin customization or better UI integration because they doesn't implement XtraUserControl (UserControl from DevExpress). The only thing I can do is go to ReactiveUI Source Code, copy the source from those controls and change in my code UserControl for XtraUserControl. And the pain is that I need to check every time ReactiveUI has upgraded if the Source Code changed and update manually.
But now in the Source Generators era... Maybe we can make it easy this "specialization". Why not create a SourceGenerators for Winforms (ReactiveUI.SourceGenerators.WinForms) that would generate an specialization by attribute (like [ReactiveUserControlAttribute()] that can get a type parameter as argument implying which base class to inherit, so if no parameter used, standard UserControl class is applied? Could be an assembly attribute, so only a single time is required to write, or an specialization per class if required.
It's doable? I think it can be exportable to any technology that currently ReactiveUI has specialized controls (WPF, etc)
Thank you for your attention
The text was updated successfully, but these errors were encountered: