Closed raffaeler closed 3 years ago
Hey @raffaeler , you can delete App.xaml and codebehind like you did, but you should still create an App object for the resources.
Adding a Program.cs file in a new project without App.xaml and App.xaml.cs that looks like this should do the trick:
namespace WpfApp1
{
class Program
{
[STAThread]
static void Main()
{
var app = new App();
app.Run(new MainWindow());
}
}
public class App : System.Windows.Application { }
}
but Visual Studio complains about resource errors
What are the errors?
@raffaeler It's also related to this issue: https://github.com/dotnet/wpf/issues/192
Take a look at the last entry there that points you to the StartObject
element that you can use for the SDK style .csproj to get this working without deleting App.xaml at all.
@thomasclaudiushuber thanks for your anwers. Isn't any way to get rid of the App.Xaml? I am programmatically loading the resources and since this is going to be a template, I would like to avoid any mistakes from the devs to declare global resources in the App.Xaml.
P.S. I added the StartupObject in my (.NET Core) WPF App.
Thanks
@miloush They are not fatal errors but very annoying. Any reference to resources declared as global (programmatically loaded) are squiggled. This obviously depends on the designer not finding the resources in xaml. To overcome the problem, there should be the support to invoke some method allowing the designer to know about the resources.
@raffaeler I see, so it is a problem with the VS designer rather than code in this repo, sounds like it might be worth trying to submit a feedback from VS then.
@miloush Nope, I don't want any VS changes. I need to get rid of the App.Xaml completely. As the InitializeComponent exists and works, there should be some way to teach the designer where the resources are.
I am sorry for being confused then, you said yourself that you can delete App.xaml
and have your own Main
used. How is that not getting rid of App.xaml completely? If you want to "teach the designer" something then that implies that the designer needs to be updated.
@miloush I have no hope if the designer needs to be updated. I was involved in the very first steps of WPF and still it take so long for any changes that I am hopeless.
@thomasclaudiushuber After declaring the StartupObject and restoring the App.xaml in the project I get the following error:
error CS0111: Type 'App' already defines a member called 'Main' with the same parameter types
The App.xaml is re-created is this one:
<Application x:Class="PuntoVendita.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
</Application>
Am I missing something?
@raffaeler Interesting. Are you using .NET Core or .NET Framework?
Works for me on .NET Core 3.1 and also .NET 5.
Here's the .NET 5 project file:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net5.0-windows</TargetFramework>
<UseWPF>true</UseWPF>
<StartupObject>WpfApp2.Program</StartupObject>
</PropertyGroup>
</Project>
Program.cs file:
using System;
namespace WpfApp2
{
class Program
{
[STAThread]
static void Main()
{
var app = new App();
app.Run(new MainWindow());
}
}
}
Which VS version are you using? On the machine I have here I'm on 16.8.1.
Update: Works also with .NET Framework for me (tried it with SDK style project file)
@thomasclaudiushuber This specific project is .NET Core 3.1, but I don't think v5 would change anything.
The Project still uses <Project Sdk="Microsoft.NET.Sdk.WindowsDesktop">
because of .NET Core 3.1.
VS is version 16.9 Preview 2
App.xaml
is included as "Application Definition" which is the usual reason for creating main entry-point.
The StartupObject
is correct (otherwise I would not see the compile error) but points to the App class (unless there is some hardcoded reason, it should not be an issue):
public partial class App : Application
{
private IHost _host;
[STAThread]
[System.Diagnostics.DebuggerNonUserCode]
public static void Main()
{
App app = new App();
app.Run();
}
// ...
Hi @raffaeler ,
yes, seems setting the App
object itself as a startup object via StartupObject
in the .csproj file causes the project to generate a Main
method in the generated App.g.i.cs file (that is part of the obj folder). Looks like that is the default behavior that you also get if you don't set the StartupObject
parameter.
If you set StartupObject
to any other class than your App
class, then it will work. This means you have to put your Main
method in another class.
@raffaeler: Can you confirm that @thomasclaudiushuber's guidance is correct and close? Thank you.
@ryalanms today I moved the main in a different class and it works but I need to hear from you if there is any way to get rid of the App.Xaml for application-wide resources and make the designer happy. In other words, can I expose a sort of "InitializeComponent" and expect the designer calling it to load the global resources?
VS responded with this suggestion for adding a WPF resource dictionary at design-time and pointed us to this SO question as an example: https://stackoverflow.com/questions/11669848/how-to-load-a-wpf-resource-dictionary-at-design-time
@raffaeler: Let me know if this answers your question. Thanks.
@ryalanms Hi again, I initially had the impression that it worked but unfortunately didn't. I don't know if this happens because my project is .NET 5 based. This is what I did:
CsProj
<ItemGroup>
<Page Include="Resources\DesignTimeResources.xaml" Condition="'$(DesignTime)'=='true' OR ('$(SolutionPath)'!='' AND Exists('$(SolutionPath)') AND '$(BuildingInsideVisualStudio)'!='true' AND '$(BuildingInsideExpressionBlend)'!='true')">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
<ContainsDesignTimeResources>true</ContainsDesignTimeResources>
</Page>
</ItemGroup>
The project folder contains the following:
And finally the DesignTimeResources.xaml
is this:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/Resources/GlobalResources.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
The GlobalResources.xaml
contains the resources (at runtime they are correctly loaded) but the designer complains:
Loading/reloading the project didn't help.
Thanks
I finally did it, thanks to [Ev] help. I created a working sample with step-by-step instructions here: https://github.com/raffaeler/WpfNoAppXaml
I have a few cases where I need to take control over app bootstrap:
I was able to delete App.Xaml and make it start with my own Main but Visual Studio complains about resource errors even if it compiles sucessfully and runs correctly.
There are two possible solutrions here: