Search code examples
c#wpfxamlresourcedictionary

How do you declare your own Main() and import ResourceDirectory


I need to customise the Main() method in my WPF application, so I have turned off the auto-generation of the main, by changing the Build Action of my App.xaml to 'Page' (instead of 'ApplicationDefinition'). However, I also need to use a ResourceDictionary, and if the App.xaml isn't marked as 'ApplicationDefinition', none of the resources get imported (I tried this, see here).

I need a custom Main() method because the application is required to be a singleton, to the main simply reads:

[STAThread]
public static void Main()
{
    MainApplication app = MainApplication.Instance;
    app.Run();
}

No how do I automatically import all resources and define my own main at the same time?

One solution is to import them programatically, e.g. like this:

ResourceDictionary dict = new ResourceDictionary();
dict.Source = new Uri("/MyProject;component/MyResourceDictionary.xaml", UriKind.Relative);
Application.Current.Resources.MergedDictionaries.Add(dict);

This solution is not acceptable, though, as I want to be able to give my application to a designer who uses Blend and may know nothing about the background of the programme. So he would not be permitted to create new resource files, which is not ideal. Any better suggestions?


Solution

  • I strongly recommend that you leave the Main() method to the default.

    what you're trying to achieve here requires no custom code, and even if it did, the Main() method is NOT the right place to put that custom code.

    You don't need to create a "singleton" property for the Application object in WPF, because WPF already does that.

    You can access the "singleton" instance of the Application object in WPF via the System.Windows.Application.Current property:

    So that if you put custom properties in the App class, like this:

    public partial class App : Application
    {
        public string MyString { get; set; }
    
        protected override void OnStartup(StartupEventArgs e)
        {
            base.OnStartup(e);
            MyString = "I'm a string in the App class";
        }
    }
    

    Then you can access that in XAML:

    <TextBox Text="{Binding MyString, Source={x:Static Application.Current}}"/>
    

    Or, if you need to access the instance of the MainWindow, then you can do:

    <TextBox Text="{Binding Title, 
                            Source={x:Static Application.Current.MainWindow}}"/>
    

    or

    <TextBox Text="{Binding DataContext.MyString, 
                            Source={x:Static Application.Current.MainWindow}}"/>
    

    for properties that are in the MainWindow's ViewModel.