dotnet / maui

.NET MAUI is the .NET Multi-platform App UI, a framework for building native device applications spanning mobile, tablet, and desktop.
https://dot.net/maui
MIT License
22.09k stars 1.73k forks source link

A global usings/namespaces file to include namespaces and inherit attributes from base page for all xaml files #3376

Open MrClan opened 2 years ago

MrClan commented 2 years ago

Summary

A global usings/namespaces file to include namespaces and inherit attributes from base page for all xaml files.

Intended Use Case

This feature request is to have the ability to be able to move any custom namespace imports, to a single file somewhere, so that they don't have to be repeated in every single xaml file over and over again.

An example would look something like this:

Current State

In current state, my pages/views looks like this:

Page1.xaml

<ContentPage ...
             xmlns:controls="clr-namespace:MyCompany.Controls;assembly=MyCompany.Controls"
             xmlns:views="clr-namespace:MyCompany.Controls;assembly=MyCompany.Views"
             xmlns:utilControls="clr-namespace:MyCompany.Controls;assembly=MyCompany.UtilControls"
             xmlns:effects="clr-namespace:MyCompany.Controls;assembly=MyCompany.Effects"
             xmlns:renderers="clr-namespace:MyCompany.Controls;assembly=MyCompany.Renderers"
             xmlns:resources="clr-namespace:MyCompany.Controls;assembly=MyCompany.Resources"
             xmlns:converters="clr-namespace:MyCompany.Controls;assembly=MyCompany.Converters"
             xmlns:behaviors="clr-namespace:MyCompany.Controls;assembly=MyCompany.Behaviors"
             xmlns:shadows="clr-namespace:MyCompany.Controls;assembly=MyCompany.Shadows"
             xmlns:ios="clr-namespace:Xamarin.Forms.PlatformConfiguration.iOSSpecific;assembly=Xamarin.Forms.Core"
             ios:Page.UseSafeArea="True"
             NavigationPage.HasNavigationBar="False"
             >

<Label Text="{x:Static resources:Strings.TitleText}" />   
...
</ContentPage>

Page2.xaml

<ContentPage ...
             xmlns:controls="clr-namespace:MyCompany.Controls;assembly=MyCompany.Controls"
             xmlns:views="clr-namespace:MyCompany.Controls;assembly=MyCompany.Views"
             xmlns:utilControls="clr-namespace:MyCompany.Controls;assembly=MyCompany.UtilControls"
             xmlns:effects="clr-namespace:MyCompany.Controls;assembly=MyCompany.Effects"
             xmlns:renderers="clr-namespace:MyCompany.Controls;assembly=MyCompany.Renderers"
             xmlns:resources="clr-namespace:MyCompany.Controls;assembly=MyCompany.Resources"
             xmlns:converters="clr-namespace:MyCompany.Controls;assembly=MyCompany.Converters"
             xmlns:behaviors="clr-namespace:MyCompany.Controls;assembly=MyCompany.Behaviors"
             xmlns:shadows="clr-namespace:MyCompany.Controls;assembly=MyCompany.Shadows"
             xmlns:ios="clr-namespace:Xamarin.Forms.PlatformConfiguration.iOSSpecific;assembly=Xamarin.Forms.Core"
             ios:Page.UseSafeArea="True"
             NavigationPage.HasNavigationBar="False"
             >

<Label Text="{x:Static resources:Strings.TitleText}" />   
...
</ContentPage>

But with this feature

GlobalNamespaces.xaml

<ContentPage ...
             xmlns:controls="clr-namespace:MyCompany.Controls;assembly=MyCompany.Controls"
             xmlns:views="clr-namespace:MyCompany.Controls;assembly=MyCompany.Views"
             xmlns:utilControls="clr-namespace:MyCompany.Controls;assembly=MyCompany.UtilControls"
             xmlns:effects="clr-namespace:MyCompany.Controls;assembly=MyCompany.Effects"
             xmlns:renderers="clr-namespace:MyCompany.Controls;assembly=MyCompany.Renderers"
             xmlns:resources="clr-namespace:MyCompany.Controls;assembly=MyCompany.Resources"
             xmlns:converters="clr-namespace:MyCompany.Controls;assembly=MyCompany.Converters"
             xmlns:behaviors="clr-namespace:MyCompany.Controls;assembly=MyCompany.Behaviors"
             xmlns:shadows="clr-namespace:MyCompany.Controls;assembly=MyCompany.Shadows"
             xmlns:ios="clr-namespace:Xamarin.Forms.PlatformConfiguration.iOSSpecific;assembly=Xamarin.Forms.Core"
             ios:Page.UseSafeArea="True"
             NavigationPage.HasNavigationBar="False"
             />

And with this file in place, all my views/pages would be simplified as shown below:

Page1.xaml

<ContentPage ...
             >
<Label Text="{x:Static resources:Strings.TitleText}" />
...
</ContentPage>

Page2.xaml

<ContentPage ...
             >
<Label Text="{x:Static resources:Strings.TitleText}" />
...
</ContentPage>

Note that, all the globally imported namespaces are available in all my views, plus any properties set in the base view or global/root page like: ios:Page.UseSafeArea="True" or NavigationPage.HasNavigationBar="False" are automatically applied with inherited values. Of course, setting the same properties in the current page/view would take preference and override any inherited values.

PS: A further enhancement, and a really useful option, could be to have a property on views to explicitly specify inheritance from the any file (base page or global file) as such:

<ContentPage ...
             inheritsFrom="GlobalNamespaces.xaml"
             >

Or even support import from multiple files:

<ContentPage ...
             inheritsFrom="GlobalNamespaces.xaml,BasePage.xaml"
             >
ghost commented 2 years ago

We've moved this issue to the Future milestone. This means that it is not going to be worked on for the coming release. We will reassess the issue following the current release and consider this item at that time.

vhugogarcia commented 2 years ago

This will be fantastic! I love this idea! Thanks for looking into!

mrlacey commented 1 year ago

I wasn't able to find this issue previously, but I've just explored this separately. https://www.mrlacey.com/2023/04/global-and-implicit-using-directives.html

janseris commented 1 year ago

@jfversluis What are the plans for this? This is an important feature for Maintainability. Avoiding large copypasting and syncing in the whole application.

jfversluis commented 1 year ago

Absolutely cool and important, but I think there are other more important things right now. I don't think we will be working on this for .NET 8.

wolfgangschneider commented 8 months ago

There was a similar system to bungle xml namespaces in Silverlight , but i forgot how.

RuddyOne commented 7 months ago

Amazing idea. This would keep so much code clean.

pboisso commented 5 months ago

+1 vote for the feature request.

mrlacey commented 5 months ago

The problem is that moving namespaces (and aliases) to a separate file, it no longer makes the file a valid XML document, and all XAML files are expected to (should) be valid XML. A consequence of such a change is that it also becomes necessary for all tooling (from MAUI, parts of VS, and from 3rd parties) to change how they parse xaml documents. To make such a change would be slow and time-consuming to avoid breaking any existing code or trying to use the new capabilities with any tool that doesn't know about this variation. (You couldn't start using this until all of your tooling pipeline was updated.)

This (the moving of shared namespaces to a separate file) is really creating a new version of XAML. If going to the trouble of creating what is essentially a new markup language, many more things could be done to offer improvements over what XAML currently offers than just extracting namespaces. That then also becomes a much bigger discussion. Sadly, given the time and resources available to the MAUI team and the widespread reluctance to use .net languages that don't come directly from Microsoft, we may be waiting a long time...

wolfgangschneider commented 5 months ago

Silverlight had a similar concept called Custom Namespaces. The keywords are XmlnsDefinition and XmlnsPrefix.

https://blogs.profitbase.com/2010/05/xml-namespace-simplified-in-silverlight-4-0/

https://www.codeproject.com/Articles/111911/A-Guide-to-Cleaner-XAML-with-Custom-Namespaces-and

dotMorten commented 5 months ago

You can do that in Maui too: https://github.com/Esri/arcgis-maps-sdk-dotnet-toolkit/blob/3dd2dcedaef617010e736a74aeab7fdf086c80df/src/Toolkit/Toolkit.Maui/AssemblyInfo.cs#L9

I think this is a cleaner solution that libraries should use more without also making your xaml invalid xml.

StephaneDelcroix commented 1 week ago

can't agree more with @mrlacey. We could think of some ways of aggregating namespaces, but we want to keep the file valide XML, and valid XAML