Skip to content
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

Discussion : Application.Styles required or Window will not Render Content #4614

Closed
jtbrower opened this issue Sep 3, 2020 · 6 comments · Fixed by #11365
Closed

Discussion : Application.Styles required or Window will not Render Content #4614

jtbrower opened this issue Sep 3, 2020 · 6 comments · Fixed by #11365

Comments

@jtbrower
Copy link

jtbrower commented Sep 3, 2020

Default Styles Required for Window to Render?

This discussion relates to a newbie mistake that could frustrate people who are trying to port a WPF application to Avalonia.

While attempting to port a portion of my application that consists of 7assemblies, I became eager to finally see zero compilation errors so I could run the application. Since this was a port, I did not start the process using the Avalonia Visual Studio project templates. However, I did create a side project using the templates and referred to it to test out approaches and to understand what needed to be changed in the WPF app.

Once I executed the application, the only thing I saw was a black Window. Black not because I set the background color to black, but rather due to an error on my part. As I walked line by line comparing the port with a running Avalonia application, I just couldn't spot what was missing.

Eventually I realized that the black Window was caused by the fact that I did not include default styles as below. Since I was porting a decent amount of code for this portion of my application, I had a lot of places where I blamed myself for making mistakes.

<Application
    xmlns="https://github.com/avaloniaui"
    x:Class="Oceanside.VirtualKeyboard.Sample.App.App"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
  <Application.Styles>
    <StyleInclude Source="avares://Avalonia.Themes.Default/DefaultTheme.xaml"/>
    <StyleInclude Source="avares://Avalonia.Themes.Default/Accents/BaseLight.xaml"/>
  </Application.Styles>
</Application>

I didn't include those lines because I didn't think any of them would be needed. My application has data templates for all of my view models, the Window itself has no decorations and I thought all style was under my control.

Technically, when I first ran the application, nothing at all showed. In an effort to debug the problem, I removed the transparency from the Window and set it to Blue. The Window would render black, almost like it wasn't rendering anything at all.

Sample Project

ContentWillNotShow.zip

Screen Shot of Running Sample App having Styles Commented Out

image

Expectations

Since default styles are not required in WPF, it took me a while to realize what was causing a blank, control-less, black Window. Its hardest to spot when you are porting existing WPF code to Avalonia. I will leave it up to your team to decide if rendering a black Window (or not rendering at all) is by design when default styles are not included. Maybe mentioning the requirement here will help and or throwing an exception with a missing styles message?

@jmacato
Copy link
Member

jmacato commented Sep 4, 2020

I think this should be pointed out in our Porting from WPF guide... This wasn't noticed much since most of folks that ports over stuff from WPF to Avalonia started with our default project template. Anyways, a great post @jtbrower ! :)

@maxkatz6
Copy link
Member

maxkatz6 commented Sep 4, 2020

Avalonia can't include these StyleIncludes by default, when it actually has two build-in themes - Default and Fluent.
Could be related #2769

@maxkatz6
Copy link
Member

maxkatz6 commented Sep 4, 2020

My application has data templates for all of my view models, the Window itself has no decorations and I thought all style was under my control

You point is, that you have styles for all controls what you need, right? And you don't want to use all of build-in styles for them.
It is true, that Avalonia requires default/fluent theme just to render Window or UserControl without any another controls.
Window and UserControl templates are not defined without it:
https://github.com/AvaloniaUI/Avalonia/blob/master/src/Avalonia.Themes.Default/Window.xaml
https://github.com/AvaloniaUI/Avalonia/blob/master/src/Avalonia.Themes.Default/UserControl.xaml

If I understood your problem correctly, you need to define these styles above as well.

@danwalmsley
Copy link
Member

@maxkatz6 i wonder if Window and UserControl templates (which match in both themes) could be combined to a single one...
and loaded by default?

@jtbrower
Copy link
Author

jtbrower commented Sep 5, 2020

This wasn't noticed much since most of folks that ports over stuff from WPF to Avalonia started with our default project template.

@jmacato IMO it made less sense for me to copy thousands of lines of XAML and code into a new blank Avalonia solution than it did to leave the code in place and modify it to match what the default Avalonia project/solution templates created in a side sample I used for comparison. Problem was, since I had my own custom App.xaml and App.xaml.cs that had to be brought in from WPF, as I ported over the resources it needed to include the Avalonia way, I assumed that the two inclusions in the sample Avalonia project were there to style elements that I thought I provided full templates and styles for. Since I had Templates and styles (or I thought) for everything I was showing, the defaults seemed like "fluff".

If I understood your problem correctly, you need to define these styles above as well.

Hi Max, I think you do understand how it was a challenge for me to find this problem. As you pointed out, I thought that I had all of the styles and templates required to render what I was showing. The Window itself was completely look-less (before I changed it bag for debugging purposes and for the sample code above). All of my view models had related DataTemplates and the controls used inside of the DataTemplates had specific Styles that set specific ControlTemplates. I essentially tried to have 100% control over everything, so I didn't see any need to bring in defaults that I wasn't going to use. I didn't provide definitions for UserControls either because I wasn't using any directly. I was inheriting from Buttons and ContentControls. In hindsight I think I did see where Avalonia itself was directly using UserControls for some components. However, the next section shows another mistake on my part, not defining expected template parts.

What WPF Devs have been Trained to Do

In fairness to Avalonia, even WPF has specific requirements for many of their ControlTemplates such that you must specifically include named parts; for example I see your Window has a PART_TransparencyFallback. In WPF the required template parts are marked on the control's class definition file using TemplatePart attributes like the example for the Calendar below.

WPF Calendar

    [TemplatePart(Name = Calendar.ElementRoot, Type = typeof(Panel))]
    [TemplatePart(Name = Calendar.ElementMonth, Type = typeof(CalendarItem))]

From Microsoft
Control authors apply this attribute to the class definition to inform template authors the types of the parts to use for styling the class. These parts are usually required in the template and have a specific predefined name.

No Need to Copy WPF

I am not suggesting that WPF be copied and I have no problem including those files.

I think the main stumbling point was not so much the requirement to include defaults, but the lack of any specific exception indicating why the Window was not rendering its content.

When I failed to include those defaults, it was essentially a "fatal" condition since the application was not capable of rendering anything but a black screen. Since the app cannot render, maybe the best way to handle this is to throw an exception? Something similar to what happens in WPF when you crash on the Dispatcher thread. In most cases, its not a recoverable situation, but the application still has the opportunity to shutdown gracefully if it listens for the specific Dispatcher exception.

All XAML developers are trained to get rid of the "fluff" right? Its just in our instinct to avoid including anything that's not needed and I made the mistake of thinking those defaults were not needed since I felt I provided definitions for everything I was using.

Thanks gents! I am ok with you closing this out if you wish. Maybe the existence of this discussion will be enough to help future devs when they see the black screen.

@jtbrower
Copy link
Author

jtbrower commented Nov 8, 2023

Excellent job.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants