I have a WPF application without an application.xaml, since I need to do the Main() method by myself. Therefore I neither have an ApplicationDefinition nor an application resource. I currently attach the resource dictionary to the application at the application startup
Of course the WPF Designer complains now about missing resources.
So I want to get rid of two problems:
- I don't want to attach the resource dictionary manually at startup
- I want to get the resources also work at design time in the WPF designer
Is there any help for this problem?
Thanks
Martin
There is a possibility to use the Main() method for yourself
Just delete the following property from the xamlcode of Application.xaml:
StartupUri="MainWindow.xaml"
Then add the following in the code-behind of the Application.xaml:
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
// My code goes here, but nothing ever happens.
base.OnStartup(e);
}
}
Now you can still use the Application.xaml for your resources and also have your specific startup procedure.
Related
I am trying to learn WPF. I have done mostly back-end programming, except I did some C++ UI programming in the nineties. So far, I have created a simple maintenance application with a few screens and I can run it fine. I can navigate around, insert records and whatnot. However, I have to set my app.xaml startup location to MainWindow.xaml and then instantiate my actual window inside the C# code of the class linked to it. If I delete the MainWindow.xaml file and set my StartupLocation to wndMyMainWindow.cs, I get an error saying that it can not find the file. Is there any way around this? It seems sort of weird to require a non C# file type in what is supposed to be a C# UI framework.
In your App.xaml remove the StartupUri="MainWindow.xaml". Then add Startup="App_OnStartup" and create the matching method in your App.xaml.cs file like:
public partial class App : Application
{
private void App_OnStartup(object sender, StartupEventArgs e)
{
// do some code stuff like initializing your ViewModel or something else
// Instanciate the view you want to display and show it
MainWindow mainWindow = new MainWindow();
mainWindow.ShowDialog();
}
}
I am really new to WPF and c#, and have some questions about how the applications are initialized. I am going through some tutorials on LINQ classes in the hopes that I can bind all of my SQL Server data with observableCollections.
One of the examples I found has a start like so (in the App.xaml.cs file):
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
MainWindow app = new MainWindow();
ProductViewModel context = new ProductViewModel();
app.DataContext = context;
app.Show();
}
}
When I run the application I get 2 main windows. The commands above execute and open the first one, but then a second one gets called from some system code which I can't see (I can see in dissasembler, but that does not really help). So it seems that the application that VS set up for me has a standard entry, but the sample code (from Rachel Lim) does not do this. I have searched for differences in various files (like App.g.i.cs which has the void Main() call) and both my application and the sample are the same. I am trying to "take control" of the application to handle creating my observablecollections with the LINQ classes. Is anyone familiar enough with VS and C# to give me some hints on what might be happening?
The problem is probably in your App.xaml which often has the following:
Application x:Class="WpfApplication1.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="MainWindow.xaml">
<Application.Resources>
</Application.Resources>
</Application>
If your App.xaml.cs opens a window in one of the events as you have demonstrated, then you need to make sure to remove that StartupUri="MainWindow.xaml" in your Application element.
I have a program wrriten in WPF (C#) where all of the elements has a style that points a static resource located in a ResourceDictionary by the name "Styles.xaml";
Since I need to have the styles customed, I use this file to change colors and fonts to elements all across the program.
The problem is, In order to see the changes I need to recompile, and to have another EXE wich is a slight differ version of the program (differ by colors).
I don't want to maintain many versions of the program.
Is it possible to have a ResourceDictionary (or any other file) outside of the compiled EXE to function as css does with HTML?
Meaning, is it possible to achieve the following: replacing the file in the folder where the EXE lies will be sufficient in order to change the colors?
Thank you.
You can obtain a ResourceDictionary instance from .xaml file (not necessary included in your project) by calling XamlReader.Load method and casting the resulting object afterwards. From that point it comes down to manipulating this dictionary in code behind. On application level you can call something like
Application.Current.Resources.MergedDictionaries.Clear();
Application.Current.Resources.MergedDictionaries.Add(dictionary);
where dictionary is the instance you have loaded. The same can be done for individual controls.
Thanks to Nikita Brizhak , I have succeeded.
Here is the full "HOW TO":
1) You need to add an OnStartUp method to App.xaml.cs. Here is the syntax:
protected override void OnStartup(StartupEventArgs e)
2) You have to clear all the resources.
Application.Current.Resources.Clear();//This is if you have on your App.xaml a load of your resource. Clear it and than load another.
//It is good to have this so you can see you style while working on the project, But on runtime to replace.
Application.Current.Resources.MergedDictionaries.Clear();
3) you Have to load your dynamic resource
Final Code:
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
Application.Current.Resources.Clear();
Application.Current.Resources.MergedDictionaries.Clear();
StreamReader stream = new StreamReader("Styles.xaml");
Application.Current.Resources.MergedDictionaries.Add(System.Windows.Markup.XamlReader.Load(stream.BaseStream) as ResourceDictionary);
}
I'm trying to run a window, close it, and then run a second window, in a similar way that seems to work with Windows Forms.
namespace WpfApplication1
{
public partial class App : Application
{
[STAThread]
public static void Main()
{
Application app = new Application();
//windowMain.Show();
app.ShutdownMode = ShutdownMode.OnExplicitShutdown;
MainWindow windowMain = new MainWindow();
app.Run(windowMain);
Window1 window1 = new Window1();
window1.Show();
app.Run(window1);
}
}
}
I've set the Build Action in the App.xaml properties from ApplicationDefinition to Page, but the programme throws an exception when window1 is initialised. What am I doing wrong?
Edit: I've modified the xaml in App.xaml as suggested by first answer and edited main as suggested by the comment.
<Application x:Class="WpfApplication1.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="MainWindow.xaml"
ShutdownMode="OnExplicitShutdown">
<Application.Resources>
</Application.Resources>
</Application>
but I'm still getting the exception.
OK this is what I've divined so far. The Solution Builder looks for a Main() function. Why its not a WinMain() function I'm still not a hundred per cent clear on. If there is no Main(), you get an error. You can have more than one Main() as long as the Project properties: "Application" page/tab: property: "StartUp Object" is set to point to one of the main()s. This is done from an automatically created drop down list.
When a “WPF Application” project is created, Visual Studio(VS) create an xaml file called “App.xaml”. This is a class declaration where “App” is derived from the “Application” Class. VS also automatically generates hidden files for an xaml file. It creates a “name.g.i.cs” file, when the xaml file is created. It creates a “name.g.cs” file the first time the project is built after the creation of the xaml file. In this case it creates “App.g.cs” and “App.g.i.cs”. These files are hidden by default. To view them, press the “Show all files” button at the top of the Solution Explorer, they can be found in “\ obj\86\Debug” folder. When you delete an xaml file the “name.g.i.cs” and the “name.g.cs” files remain and are not deleted.
The “App.xaml” file’s “build Action” property is set to “Application Definition” when created by VS. When this property is set to “Application Definition” a Main() function is automatically created in “name.g.i.cs”:
[System.STAThreadAttribute()]
[System.Diagnostics.DebuggerNonUserCodeAttribute()]
public static void Main()
{
WpfApplication8.App app = new WpfApplication8.App();
app.InitializeComponent();
app.Run();
}
When this property is set to “Page”, the Main() function is automatically removed by VS. You can create new “Application” derived classes in code or in xaml. I haven’t found a neat way to do it in xaml. There doesn’t seem to be a template for an xaml “Application” derived class. I created a “.cs” code file and then renamed it to an .xaml file. For some reason VS won’t allow you to have more than one xaml “Application” declaration file set to “Application Build”, it doesn’t even give you the option of choosing one in the "Project: Properties: Application": “Startup Object” property.
As you can see in the hidden Main(), an instance of “App” is instantiated and run. If using your own Main() function: an instance of, the base “Application” class, or an “Application” derived class (whether declared in code or in xaml), can be declared and run. The “Application” class should only be instantiated once and should only be run once. If the “Application” derived class is declared in xaml then a simple application can be run by using the StartUpUri property in the xaml file: StartupUri="Windowname.xaml". Alternatively the top level UI programme logic can be placed in a Startup event handler. If “Startup="Application_Startup" is placed in the “App.xaml” file then an event handler can be written:
private void Application_Startup(object sender, StartupEventArgs e)
{
MainWindow windowMain = new MainWindow();
windowMain.ShowDialog();
Window1 window1 = new Window1();
window1.ShowDialog();
Shutdown();
}
You have to use ShowDialog() here, because it blocks until the window is closed. If you used Show() instead, it would show one window, then immediately show the other one and shutdown the application. In this case there's no need to call the Run() method yourself, that's done automatically.
The “Application” class instance can be run in code whether its declared in code or in xaml. You can then perform initialisation code prior to calling Run(). This would be placed in the Application_ Startup() event handler using the other way. However, if the “Application.Run” call is ever made in the programme, then no windows should be opened (using show() or ShowDialog()) in Main() or anywhere outside of the Application Class or within events and functions called from those events, called during “Application.Run()”.
The Application class has a ShutdownMode property (Application.ShutdownMode). The default for this is: “OnMainWindowClose”. This property can also be set to “OnLastWindowClose” or “OnExplicitShutdown” in code or in the xaml. You will need to reset this if you don't want the programme to close down when the MainWindow is closed.
I think for my purposes it is better not to use the Application class at all and just call the windows using Show() and “ShowDialog()”. This way I can use WPF pages but I could also call Windows Forms, or DirectX screens, as long as they are not open at the same time, or have no UI at all, if the programme is running remotely. Is there any reason for not doing it this way?
I think your application is shuting down when you close the first window. You need to set Application.ShutdownMode to OnExplicitShutdown.
If all you want to do is to show one window, when that closes, show another and when that closes, shutdown the whole application, you should keep the Build action as ApplicationDefinition, set ShutdownMode to OnExplicitShutdown (probably in App.xaml, but you can it in code-behind too) and put the following code in an event handler of the Startup event of your application:
private void Application_Startup(object sender, StartupEventArgs e)
{
MainWindow windowMain = new MainWindow();
windowMain.ShowDialog();
Window1 window1 = new Window1();
window1.ShowDialog();
Shutdown();
}
You have to use ShowDialog() here, because it blocks until the window is closed. If you used Show() instead, it would show one window, then immediatelly show the other one and shutdown the application.
There's no need to run the Run() method yourself, that's done automatically.
I'm having problems understanding how WPF app.xaml works. Is it like Main method in winforms programing?
What I want is a MainController class which keeps track of my Window object. For example:
public MainController()
{
_windowMain = new WindowMain(this);
}
public WindowMain GetWindowMain
{
get { _windowMain; }
}
And so on with all the windows I have in my project. But where should my MainController be initialized?
Check the StartupUri property of the App.xaml file. It links in a Window's XAML file within your project to be launched at startup.
If you want to avoid this, then I believe you can override a method in App.xaml.cs to launch the window explicitly via your controller.
You should understand that the compiler makes a class called 'App' that overrides System.Windows.Application by compiling your App.xaml and App.xaml.cs files. Check the documentation for that class to learn more about the lifecycle management of your WPF application.