AvaloniaUI / Avalonia

Develop Desktop, Embedded, Mobile and WebAssembly apps with C# and XAML. The most popular .NET UI client technology
https://avaloniaui.net
MIT License
26.12k stars 2.26k forks source link

Create a relative or property of `<StyleInclude/>` that gets the source from a XAML namespace and class #17156

Open WillPittenger opened 2 months ago

WillPittenger commented 2 months ago

Is your feature request related to a problem? Please describe.

I needed some custom styles for some stock controls. I also needed those styles accessible from many different assemblies. (At least 2 so far with more expected.) Unfortunately, <StyleInclude/>'s Source property requires a URL. I'd much rather reference the styles as a class in one of my platform assemblies. We don't currently have much of a website yet. So the most I could do is reference the latest version in GitHub's change tracker. But our project name isn't even settled. We keep rejecting names as not descriptive of the program, taken, or no valid icon fits into a 16x16 notification icon.

Describe the solution you'd like

I don't know if Avalonia style pages get compiled to a C# class, but that would be needed.

Describe alternatives you've considered

As mentioned, I'm copying the styles to each assembly and then adding <StyleInclude Source="../PrefsStyles.axaml"/> But then I have to copy that file around. Since we don't have a fixed website and even our GitHub location probably will change, that's all I have.

Additional context

Rider insists assuming the App.xaml will provide the classes is an error if it's in a different assembly.

stevemonaco commented 2 months ago
  1. Assign an x:Class: <Styles x:Class="x:Class="YourNamespace.AppStyles ...>"
  2. Create a code-behind file: AppStyles.axaml.cs
    namespace YourNamespace;
    public partial class AppStyles : Styles
    {
    }
  3. Add it to a Styles collection somewhere in your visual tree. For the root, do it in App:
    public override void OnFrameworkInitializationCompleted()
    {
    Styles.Add(new AppStyles());
WillPittenger commented 2 months ago

And how would I convince Rider that the styles are available in all my assemblies. This project has to be divided by abstraction layers. We're looking at a dedicated desktop UI, a mobile UI, a web client, and possibly a TUI for those that don't want the GUI. I came to the conclusion that one UI doesn't fit all of those. A good UI for a desktop would be poorly suited for a phone. Conversely, a phone UI wouldn't work on a desktop.

Making things harder, our client is going to initially be an IRC client, but would later allow 3rd party protocol assemblies that would need to add their own UI. See ChatZilla Replacement Project.

maxkatz6 commented 2 months ago

And how would I convince Rider that the styles are available in all my assemblies

Just a combination of C# class namespace and class visibility modifier.

I.e., following @stevemonaco example, you will be able to reference that style in other projects via:

<Application ...
             xmlns:ns="using:YourNamespace">

<Styles>
     <FluentTheme />
     <ns:AppStyles />
</Styles>
maxkatz6 commented 2 months ago

For example, well-known <FluentTheme /> was created exactly this way, as a XAML file with attached C# class to it. It just doesn't require a namespace, as it's reserved for Avalonia.

WillPittenger commented 2 months ago

The problem is the App.xaml is in the wrong assembly. Rider won't see it and claim my style class or resource doesn't exist while I'm editing xaml.

maxkatz6 commented 2 months ago

Sorry, I don't understand what you mean by the wrong assembly. If namespace is correct and dependencies are non-bidirectional (following rules of .NET CLR), it should work fine. Can you provide more info on your errors?

WillPittenger commented 2 months ago

Now you got me confused. DLL assemblies normally don't know much about the app calling on their services. So how can I or Rider assume that App.xaml in an unrelated assembly will have an Avalonia style matching something like "Button.ResetBtn"?

maxkatz6 commented 2 months ago

DLL assemblies normally don't know much about the app calling on their services

Yes. And in your situation assembly containing style being included shouldn't know about App assembly.