dotnet / winforms

Windows Forms is a .NET UI framework for building Windows desktop applications.
MIT License
4.35k stars 965 forks source link

Introduce ApplicationDefaults for Application and the Application Framework #4958

Open KlausLoeffelmann opened 3 years ago

KlausLoeffelmann commented 3 years ago

Rationale:

We recently discussed and implemented a new method named SetDefaultFont on the Application type, which allows the User to, well, do exactly this: Set a Default font. The primary motivation was for migration of legacy Framework WinForms apps, which had pixel-perfect Form designs based on the previous standard font, to still work in .NET. without completely redoing the layout.

While having this method is important, the means to apply it doesn't go far enough: Our concern is especially for VB (@KathleenDollard) that we will have problems in the future to find a feasible way to apply further default values, should we need them. And we most likely will.

While we could introduce an other application event ApplyDefaultFont for the Application Framework, our concern is, that we wouldn't stop introducing more and more patterns like this, and this would extremely affect the clarity and ultimately the discoverability of new APIs around new default values, since we would flood VB with new "ApplyDefaultxxx" events over the time.

Introducing ApplicationDefaults, Defaults Property and ApplyApplicationDefaults event.

Rather, we'd like to introduce for VB a new Application Framework event called ApplyApplicationDefaults. This event would provide access to a Defaults Property of a new type ApplicationDefaults, and via a series of SetDefaultXXX extension methods, we could feed the internal collection of Defaults Values of the Application object/type in a type safe and easily extendable way.

This would also mean, we would introduce a Defaults Property of type ApplicationDefaults on the Application type/object.

Setting default values (of which only DefaultFont via the extension method SetDefaultFont) would exist as the first in the .NET 6 timeframe) in C# would be done like this:

image

In VB, we'd be introducing the ApplyApplicationDefaults event, and it usage would be similar to applying the HighDpiMode via the ApplyHighDpiMode event of the VB Application Framework:

image

At the same time, we would need to apply the changes for setting the Defaults for the templates in VB and in C#.

https://github.com/dotnet/winforms/pull/3705 already has the implementation for this proposal.

merriemcgaw commented 3 years ago

Next Steps: @KlausLoeffelmann to formalize the API Diff and tag appropriate people. @russkie to think a bit more on corner cases.

RussKie commented 3 years ago

Conceptually the proposal makes sense, but I struggle to think of anything else what we could consider as an "application default", which would justify this new API. Application defaults for me mean a behavioural consistency, not so much a presentation or visual consistency. The latter fall into a "theming" category (e.g. "default colour" or "default button size"), which is an orthogonal concern.

What other application default (i.e. a behavioural consistency) do you see in the medium/long term future?

With the regards to VB, as we've talked offline few times, my preference would be to move away from the AF to Roslyn source generators, and possible move away from myapp file too. This is certainly a separate discussion, so I won't go in there now.

KlausLoeffelmann commented 3 years ago

The more I thought about your concept https://github.com/dotnet/winforms-designer/issues/3192 the more I got concerned for "just" having simple methods for setting a default value (or default values per se). And the reason is the enormous potential of that proposal.

Guaranteeing a unique style in Customer's Forms Design

Think about it: Why would we stop with the Font? We could also apply the same principle let's say for the sizes of Controls, and your proposal is totally up to that: If you have a WinForms team developing a large App, you want to enforce a consistency for the UI elements in each Form or User Control. With Defaults we could as one example allow a mapping of Controls with their default sizes defined in a project. Since the Designer could read that mapping, it would apply those default sizes, and whenever a control gets added to the Form, it would have exactly those sizes which we had defined for that. That would save the customers a lot of money, since Forms would apply to those standards without tweaking it. (Sure, you can write Analyzers for that, but that's not practical, since they would show up in the Designer code which is not supposed to be edited directly. It's even worse for localized Forms, where the Analyzers wouldn't be able to detect the right sizes). But then for the CodeDomSerializer to work correctly, we would need those default size settings made known to the application: And such a Defaults-Collection - since it's dynamic internally - could handle that without problems!

By the way: For a consistent layout, I'd love defaults for Padding and Margin for different container controls mappings as well!

Ambient Properties

Besides of the Font, we use other ambient properties in WinForms. Ambient properties should always also have Default values.

Default Mappings for DataBinding

Going forward with DataBinding, default converters or default controls for certain Data Source Types come to mind. Those are currently defined in the VS settings! I don't think that that is the correct spot to define those. In combination with your proposal, a Defaults property could also store those mappings, and we would even be able to generate dynamic binding based on a mapping at runtime. It would save a LOT of ceremony, and would again drastically reduce development costs for our customers. Not to mention to take away the "prone to error" which comes which each Designer property binding. (SetDefaultBindingUpdate, SetDefaultBindingControl(datasourcetype,controltype), SetDefaultBindingConverter(dataSourceType,converterType).

Reducing the Code being serialized and re-generated

The more Default values a project can define, the less code needs to be generated. And then the less changes are necessary, when a Form gets edited. This also reduces the potential of GitHub changes from edit to edit, when the Designer code is kept to a minimum to begin with.

Conclusion

So, these are ideas which I had just by thinking about your proposal for 20 minutes. I think the potential for this is really big. Are we going to do all that? Probably not! But having a concept which allowed for it if we would do it, I think is important. That's why I think we should have it this way.

And then real brief for VB: We need to address the Defaults now, because the current workaround with the ApplyHighDPIMode Event falls apart with .NET 7. Since we can't (and also won't) phase out the ApplicationFramework in .NET 6, we would need a VB-style way to apply the defaults.

KathleenDollard commented 3 years ago

I like the idea of the Defaults, even if we aren't sure how far ranging they are going to be. If we do not find more things to default in the near future, this does not stink too much, and I highly expect we will.

I am not sure on the name of the property on the VB event being ApplicatinsDefaults, rather than just Defaults.

I would love to hear more ideas on evolving the application framework story using source generators. From a VB perspective, we want the user experience to be quite similar to the Framework experience. If WinForms has a different perspective, we can chat. At any rate, for .NET 6, we need the event.

KlausLoeffelmann commented 3 years ago

I am not sure on the name of the property on the VB event being ApplicatinsDefaults, rather than just Defaults.

Yes, makes sense.

RussKie commented 3 years ago

I like the idea of the Defaults, even if we aren't sure how far ranging they are going to be. If we do not find more things to default in the near future, this does not stink too much, and I highly expect we will.

Conceptually I am not against the idea, but at the moment I am unable to see what these default values are, and what use cases we will addressing. Without this I have a strong feeling we're trying to add/modify API just in case in the future someone will may need something. This statement summarises it:

While having this method is important, the means to apply it doesn't go far enough: Our concern is especially for VB (@KathleenDollard) that we will have problems in the future to find a feasible way to apply further default values, should we need them. And we most likely will.

The only problem (that I see) that we have and that we need to fix - is to update VB Application Framework to accommodate the default high dpi and font properties. For a number of reasons this causes an unnecessary amount of pain (e.g. dotnet/project-system#7236, dotnet/project-system#7240, and dotnet/project-system#7241). In my opinion there are other ways of solving this problem.

I would like to understand use cases for each "default that will most likely need", and discuss appropriate solutions before deciding that we should shoehorn everything into "application defaults". There's a real risk here turning the Application object into an incoherent dump of unrelated "things".

Guaranteeing a unique style in Customer's Forms Design

As I said earlier in my opinion this is a completely orthogonal concern - this is theming/styling, and this is what theming API are supposed to address. But if we for moment consider this - how would these default be enacted/enforced at the runtime and the design-time?

Default Mappings for DataBinding

Going forward with DataBinding, default converters or default controls for certain Data Source Types come to mind. Those are currently defined in the VS settings! I don't think that that is the correct spot to define those. In combination with your proposal, a Defaults property could also store those mappings, and we would even be able to generate dynamic binding based on a mapping at runtime. It would save a LOT of ceremony, and would again drastically reduce development costs for our customers. Not to mention to take away the "prone to error" which comes which each Designer property binding. (SetDefaultBindingUpdate, SetDefaultBindingControl(datasourcetype,controltype), SetDefaultBindingConverter(dataSourceType,converterType).

Why is this an application concern? Sure, these are perfect clients for source generators, but I am unable to see why these must be tacked on to the Application object.

Reducing the Code being serialized and re-generated

The more Default values a project can define, the less code needs to be generated. And then the less changes are necessary, when a Form gets edited. This also reduces the potential of GitHub changes from edit to edit, when the Designer code is kept to a minimum to begin with.

Again, these could be automated with source generators, but I can't see how these are Application level concerns.

Ambient Properties

Besides of the Font, we use other ambient properties in WinForms. Ambient properties should always also have Default values.

This may be valuable. Do you have any specific values in mind? What use cases would we be addressing?

KlausLoeffelmann commented 3 years ago

Conceptually I am not against the idea, but at the moment I am unable to see what these default values are, and what use cases we will addressing.

Then let’s hold this off a bit until we can have explored a few ideas around this with concrete implementation prototypes. It shouldn’t take more than a day or so, and I think it will become much clearer then.

Again: if we‘re almost all positive that there are more default values to come, and SetFont won’t be the only one, we shouldn’t rush something which we can later no longer change.

Question: Does this stand in the way for generating the code from the csproj/vbproj for your other proposal?

RussKie commented 3 years ago

No, at this stage this doesn’t affect #4909.

From: Klaus Löffelmann @.> Sent: Tuesday, June 1, 2021 2:45 AM To: dotnet/winforms @.> Cc: Igor Velikorossov @.>; Mention @.> Subject: Re: [dotnet/winforms] Introduce ApplicationDefaults for Application and the Application Framework (#4958)

Conceptually I am not against the idea, but at the moment I am unable to see what these default values are, and what use cases we will addressing.

Then let’s hold this off a bit until we can have explored a few ideas around this with concrete implementation prototypes. It shouldn’t take more than a day or so, and I think it will become much clearer then.

Again: if we‘re almost all positive that there are more default values to come, and SetFont won’t be the only one, we shouldn’t rush something which we can later no longer change.

Question: Does this stand in the way for generating the code from the csproj/vbproj for your other proposal?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHubhttps://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Fdotnet%2Fwinforms%2Fissues%2F4958%23issuecomment-851593263&data=04%7C01%7Cigor.velikorossov%40microsoft.com%7Cab3ed10020ce4b3a852908d92453604d%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C637580762804369024%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&sdata=Jec5reaYfxY%2BYKhbVEVJVihZgOcphQkFFY2LaD0ly%2Fs%3D&reserved=0, or unsubscribehttps://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Fnotifications%2Funsubscribe-auth%2FABBTEXUEMDMS3BWPLPRFSILTQO4HJANCNFSM45LFTQFQ&data=04%7C01%7Cigor.velikorossov%40microsoft.com%7Cab3ed10020ce4b3a852908d92453604d%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C637580762804379017%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&sdata=6jKMubgcxURslzEaP3nju5IorUFfZolfE0M4%2BHhAS3M%3D&reserved=0.

KlausLoeffelmann commented 1 year ago

This is something we need to further discuss in the context of going forward with a series of other feature, also in the light of how Windows is going forward with Win32 support for UI modernization in general.

For that reason, bumping this to .NET 9.

@JeremyKuhne, @merriemcgaw FYI.