How to use .NET 4 SplashScreen in a WPF Prism based application? - c#

I am trying to use a .NET 4 SplashScreen in a Prism based WPF application. I have used the SpashScreen by setting the build action on the image to SplashScreen.
The application used to keep on crashing with a System.Resources.MissingManifestResourceException. Finally I figured out that if I add a StartupUri="MainWindow.xaml" in the App.Xaml file, the SplashScreen works fine.
<Application x:Class="Application"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="MainWindow.xaml">
</Application>
But in a prism application, we cannot have a StartupUri. Everything is done in the Bootstrapper.
So what do I need to do manually that StartupUri did to make the SplashScreen work?
Update 1: The complete exception message is:
System.Resources.MissingManifestResourceException was unhandled
Message=Could not find any resources appropriate for the specified culture or the neutral culture. Make sure
"Application.g.resources" was correctly embedded or linked into
assembly "Application" at compile time, or that all the satellite
assemblies required are loadable and fully signed.
Update 2:
I have figured out the adding or removing the StartupUri does not matter. What matters is that I have an additional WPF Window (other than App.xaml) or 2 dummy entries in the App.Resources tag.
<Application.Resources>
<Style x:Key="Dummy"/>
<Style x:Key="Dummy1"/>
</Application.Resources>
If I do not do this, the Application.g.resources file is not created in obj file and hence not embedded in the executable.
Adding two dummy resource entries was brought to my attention by this blog post.
Update 3:
My question was answered by Bob Bao on MSDN forum here. Also It seems Kent was trying to point me in the same direction.
Do not set the build action of the image to SplashScreen. Instead:
Add the code in the App OnStartup method as:
protected override void OnStartup(StartupEventArgs e)
{
SplashScreen splashScreen = new SplashScreen("splashscreen.png");
splashScreen.Show(true);
base.OnStartup(e);
Bootstrapper bootstrapper = new Bootstrapper();
bootstrapper.Run();
}
"splashscreen.png" is one image in the project, and its "Build Action"
is "Resource".

Simply define your own entry point which firstly shows the splash screen and then bootstraps Prism. In your project properties, set the entry point to your custom entry point.
internal static class Entry
{
public static void Main(string[] args)
{
var splashScreen = ...;
splashScreen.Show();
var bootstrapper = ...;
bootstrapper....;
}
}

Please check this adress : http://prismsplashscreen.codeplex.com/
There is a full example with prism

Related

Unable to Use BreakPoints After Trying to Add Command-Line Support

Update 3
This was actually being caused by a Post-Build action I included which uses ILMerge. See here for more details
Update2
It seems this was not directly caused by adding the command-line support, but I still don't know what did cause it. See SO question for more details.
Update
After making the below changes to allow command-line support, I cannot step through the program with this message on all my breakpoints:
The breakpoint will not currently be hit. No symbols have been loaded for this document
I checked this SO answer and found that I am missing the file Microsoft.VisualStudio.Debugger.Runtime.pdb but I have no idea where it has gone ..
Is there any reason why this would happen because of the App.xaml update?
I have a WPF application for which I need to implement command-line arguments.
Following the answer at this SO question, I amended App.xaml to remove the StartUpUri attribute:
<Application x:Class="WpfFileDeleter.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfFileDeleter"
>
<Application.Resources>
</Application.Resources>
</Application>
I then added an override method to App.xaml.cs:
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
e.Args.Contains("MyTriggerArg")
{
// Do some stuff
}
}
But after inserting a break-point at the top of OnStartUp and debugging the application in Visual Studio, it just hangs in a Ready state but never actually allows me to step through the program.
I tried the following values for StartUpUri:
StartUpUri = "App.xaml"
StartUpUri = "App.xaml.cs"
StartUpUri = "App.xaml.cs.OnStartUp"
But the application just throws a "Cannot locate resource" IOException
According to ethicallogics's answer, it is enough to define startup parameter in
app_start event handler. if you delete starupuri from xaml you need to define somethingelse in sratup handler instead of that
How to start WPF based on Arguments
So App.xaml looks like this:
<Application x:Class="MonitorTool.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:MonitorTool"
StartupUri="Views/SplashScreen.xaml"
Exit="Application_Exit">
</Application>
in my App.xaml.cs I got this code:
public partial class App : Application
{
private void Application_Exit(object sender, ExitEventArgs e)
{
//Some settings savin here...
}
}
When you use the XAML way for StartUp make sure the Namespace is right. I got my MainWindow.xaml in a folder called Views.
Or you create the startup like this: Startup="Application_Startup"
and create a Method in the App.xaml.cs file. Again check for namespaces to make sure everything is right here.
Since your app is building I guess this should work and you should at least reach this method.
private void Application_Startup(object sender, StartupEventArgs e)
{
MainWindow window = new MainWindow();
window.Show();
}
Note
When working with arguments you don't need to use the override OnStartup()simply do it like this:
private void Application_Startup(object sender, StartupEventArgs e)
{
string[] args = e.Args;
//Check for some value (for/foreach-loop) and do some stuff
MainWindow w = new MainWindow();
w.Show();
}

How does the WPF Designer know which resource to use?

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.

WPF C# Application I get 2 main windows

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.

How to Show an External WPF Before MainWindow?

My WPF application calls upon a separate project to handle a login process BEFORE the Main Window in my application is shown. This creates a problem and causes "Application Shutdown" errors because the FIRST window in the application has closed. How can I handle the login process BEFORE my Main Window is shown? Every search I find comes up with references to Prism or MEF... which I cannot use.
If you want to control everything from the very start of your application, you need to create your own main method and use this as "start object" (see project properties). More details can be found in another SO answer, but this is its essence:
[STAThread]
public static void Main(string[] args)
{
// Do anything you like before running the main window.
// ...
// Proceed with usual application flow.
var app = new MyApplication();
var win = new MyWindow();
app.Run(win);
}
To prevent the application shutdown error, you can change Application.ShutdownMode to OnExplicitShutdown. And explicitly call Application.Shutdown Method to close your application when needed.
Have you tried adding code to the App.xaml.cs file? There are places you can place code in there that runs before the main window is opened. In addition to a constructor, there's the Startup event that you can assign a handler to in the App.xaml file:
<Application x:Class="CarSystem.App" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
DispatcherUnhandledException="App_DispatcherUnhandledException"
Exit="Application_Exit"
Startup="Application_Startup"
StartupUri="MainWindow.xaml">
And, of course there's the Main method in the same file that you could throw code into, as well.

Replacing Merged Resource Dictionaries on Load of Silverlight Application

I have a set of styles and brushes defined in a ResourceDictionary that I am loading as a MergedDictionary in XAML of my top-level control:
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/MyAssembly;component/Styles.xaml"/>
</ResourceDictionary.MergedDictionaries>
I am trying to optionally replace some of these styles & brushes if a different XAML file exists in the XAP with its own ResourceDictionary. I am trying to merge in this dictionary at runtime before InitializeComponent() is called on my user control. I am using the following code to attempt to do this:
public static class StyleLoader
{
public static void MergeStyle(string xamlUri)
{
try
{
XDocument xaml = XDocument.Load(xamlUri);
ResourceDictionary rd = XamlReader.Load(xaml.ToString()) as ResourceDictionary;
Application.Current.Resources.MergedDictionaries.Add(rd);
}
catch (XmlException ex)
{
// if the file doesn't exist, we can't add it
}
}
}
The resource dictionary from the optional file is loaded fine and merged, however my original set of styles always seems to be overriding this. If I comment out the merged dictionary in XAML and simply load them at runtime in order it works perfectly:
StyleLoader.MergeStyle("/MyAssembly;component/Styles.xaml");
StyleLoader.MergeStyle("BrushReplacements.xaml");
InitializeComponent();
My problem with this solution is that without the default styles in XAML, I can not open the project in Blend. Anyone have any ideas for a solution that will keep my default styles known to Blend but allow me to optionally override them at runtime with a dynamically loaded resource dictionary? Thanks!
Here is a solution where colors/brushes are applied with bindings instead of referring directly to the static resources:
http://blogs.msdn.com/corrinab/archive/2009/11/24/9927729.aspx
Part two:
http://blogs.msdn.com/corrinab/archive/2009/12/02/9931283.aspx
Currently I think something like this is the best way of dealing with dynamically switching themes at runtime. But it does require a lot of work to port an existing application to use a mechanism like this.

Categories