DispatcherTimer and Show Modal Window - c#

Let's see if anyone can explain me this behaviour and maybe how can I solve this. I have a WPF app, and in my ViewModel I have a DispatcherTimer. In that ViewModel i have a command to show a modal window, something like this:
private void ShowWindowCommandExecuted()
{
wnNewWindow window = new wnNewWindow();
window.ShowDialog();
}
When i call this Command from a button, the new window is shown and the DispatcherTimer keeps running in the background. So far so good. The problem is when i try to show the window from the DispatcherTimer like this:
DispatcherTimer timerInstrucciones;
timerInstrucciones = new DispatcherTimer();
timerInstrucciones.Interval = TimeSpan.FromMilliseconds(1000);
timerInstrucciones.Tick += (s, e) =>
{
wnNewWindow window = new wnNewWindow();
window.ShowDialog();
};
timerInstrucciones.Start();
In this case, the new window is also shown, but as long it is visible, the DispatcherTimer stops "ticking". I understand the DispatcherTimer runs in the UI thread, but why it behaves in a different way in this case?

Generally, ShowDialog is a modal dialog that will block the calling thread, and show the dialog. It will also block interaction with the parent/owning window too.
As long as you close the Modal Dialog, the UI-Thread is blocked. Because its a DispatcherTimer, it belongs to the Window's Dispatcher and runs in the same thread. So if this thread is blocked, the DispatcherTimer stops running.
UPDATE BASED ON YOUR COMMENTS:
I haven't went through any documentation on this, but the basic difference would be DispatcherTimer will run Synchronously and not in Asynchronous way.
Won't block the Dispatcher:
timerInstrucciones.Tick += (s, e) =>
{
this.Dispatcher.BeginInvoke(new Action(() =>
{
wnNewWindow mn = new wnNewWindow();
mn.ShowDialog();
}));
};
Will block the Dispatcher:
timerInstrucciones.Tick += (s, e) =>
{
this.Dispatcher.Invoke(new Action(() =>
{
wnNewWindow mn = new wnNewWindow();
mn.ShowDialog();
}));
};
Since, Dispatcher will Invoke the Event on every n seconds, Event cannot be called anymore, if the thread got blocked for any operation inside the calling Event .

Related

how to avoid Server busy window if used thread.join() in wpf c#

I have a c++ application and use clr to call the below c# method. Everything is going good except for one thing. As wpf window needs STA thread, I'm trying to create a new thread with STA state and start it. This makes the wpf window modeless, even if the window is started with show dialog. So I tried using thread.join() to make the caller thread to wait until the thread completes or window closes. using thread.join() shows server busy window after a few seconds. (I'm not doing any operation related to the internet in my application).
How to make the caller thread to wait until the window closes? or How to get rid of Server busy window?
void ShowWindow()
{
_ownerHandle = Process.GetCurrentProcess().MainWindowHandle;
Thread newWindowThread = new Thread(new ThreadStart(() =>
{
MyWpfWindow window = new MyWpfWindow();
MyWpfWindowViewModel vm = new MyWpfWindowViewModel();
WindowInteropHelper helper = new WindowInteropHelper(window);
helper.Owner = _ownerHandle;
window.DataContext = vm;
window.ShowDialog();
}));
// set the apartment state this will only invoke the WPF window
newWindowThread.SetApartmentState(ApartmentState.STA);
newWindowThread.IsBackground = true;
// start the thread
newWindowThread.Start();
//waits this thread here untill the newWindowThread execution completes.
newWindowThread.Join();
}
Also, I tried with a while loop as below to block the current main thread.
while(!windowShown)
{
}
in the place of newWindowThread.join(). After using this, my window is not visible.
I'm getting a server busy window as below
Calling Join() blocks the current thread. If you want to wait asynchronously, you could use a SemaphoreSlim:
static async Task ShowWindowAsync()
{
SemaphoreSlim semaphore = new SemaphoreSlim(0, 1);
_ownerHandle = Process.GetCurrentProcess().MainWindowHandle;
Thread newWindowThread = new Thread(new ThreadStart(() =>
{
MyWpfWindow window = new MyWpfWindow();
MyWpfWindowViewModel vm = new MyWpfWindowViewModel();
WindowInteropHelper helper = new WindowInteropHelper(window);
helper.Owner = _ownerHandle;
window.DataContext = vm;
window.Closed += (s, e) =>
{
semaphore.Release();
semaphore.Dispose();
};
window.ShowDialog();
}));
// set the apartment state this will only invoke the WPF window
newWindowThread.SetApartmentState(ApartmentState.STA);
newWindowThread.IsBackground = true;
// start the thread
newWindowThread.Start();
//waits this thread here untill the newWindowThread execution completes.
await semaphore.WaitAsync();
}

Windows Forms: UI threads flow with Show() and ShowDialog()

While developing a solution on Windows Forms I went into a routine of showing continuous progress to user. I implemented simple dummy window with continuous progress bar:
In solution tree it is situated on the same level as the Main Window:
The simplest working approach to show continuous progress while doing something is the following code. It does work:
//This method works
private void DoSomeBackgroundStuffWithShow()
{
ContinuousProgressWindow continuousProgressWindow =
new ContinuousProgressWindow();
BackgroundWorker backgroundWorker = new BackgroundWorker();
backgroundWorker.DoWork += (sender, arguments) =>
{
//Do some stuff for 4 seconds
Thread.Sleep(4000);
};
backgroundWorker.RunWorkerCompleted += (sender, arguments) =>
{
//Window is closed when needed. Great!
continuousProgressWindow.Dispose();
};
continuousProgressWindow.Show(this);
backgroundWorker.RunWorkerAsync();
}
But I need this window to appear topmost and block its parent while working. The following code is quite similar, and it does not work - the dialog is shown, but never closed:
//This method DOES NOT WORK
private void DoSomeBackgroundStuffWithShowDialog()
{
ContinuousProgressWindow continuousProgressWindow =
new ContinuousProgressWindow();
BackgroundWorker backgroundWorker = new BackgroundWorker();
backgroundWorker.DoWork += (sender, arguments) =>
{
//Do some important stuff for 4 seconds
Thread.Sleep(4000);
};
backgroundWorker.RunWorkerCompleted += (sender, arguments) =>
{
//None of the following work for "ShowDialog() method"
//Ran with debugger - breakpoints not hit!
continuousProgressWindow.DialogResult = DialogResult.OK;
continuousProgressWindow.Close();
continuousProgressWindow.Dispose();
};
continuousProgressWindow.ShowDialog(this);
backgroundWorker.RunWorkerAsync();
}
Then, I realize the problem is about UI threads flow: when the progress window is ran as a dialog, MainWindow thread is frozen and it cannot be invoked by BackgroundWorker in RunWorkerCompleted delegate to close the dialog.
What is the simplest solution to make it work as wanted?
continuousProgressWindow.ShowDialog(this);
backgroundWorker.RunWorkerAsync();
You've got a simple chicken-and-egg problem, you don't start the worker until after the dialog closes. ShowDialog() is a blocking call. So the RunWorkerCompleted event doesn't fire because the worker didn't get started. The simplest workaround is to swap the two statements:
backgroundWorker.RunWorkerAsync();
continuousProgressWindow.ShowDialog(this);
That is not entirely safe to do. Not a problem with this snippet but in real code there is a danger that the worker completes before the dialog is displayed. Low odds but not zero. To solve that, you want to delay the worker until you are sure the dialog is up and running. That can be done with an AutoResetEvent that is Set() by the dialog's OnShown() method. Or, more elegantly, by taking advantage of a trick:
this.BeginInvoke(new Action(() => backgroundWorker.RunWorkerAsync()));
continuousProgressWindow.ShowDialog(this);
The delegate target of Control.BeginInvoke() runs when the program re-enters the message loop. That happens after the dialog becomes visible :)
The issue here is that you are calling continuousProgressWindow.ShowDialog(this) before backgroundWorker.RunWorkerAsync(). So backgroundWorker.RunWorkerAsync() will be called once you close the window.
I think following code should work, as suggested by #Steven Mills also.
private void DoSomeBackgroundStuffWithShowDialog()
{
ContinuousProgressWindow continuousProgressWindow =
new ContinuousProgressWindow();
BackgroundWorker backgroundWorker = new BackgroundWorker();
backgroundWorker.DoWork += (sender, arguments) =>
{
//Do some important stuff for 4 seconds
Thread.Sleep(4000);
};
backgroundWorker.RunWorkerCompleted += (sender, arguments) =>
{
//None of the following work for "ShowDialog() method"
//Ran with debugger - breakpoints not hit!
continuousProgressWindow.DialogResult = DialogResult.OK;
continuousProgressWindow.Close();
continuousProgressWindow.Dispose();
};
backgroundWorker.RunWorkerAsync();
continuousProgressWindow.ShowDialog(this);
}

Dispatcher.CurrentDispatcher.BeginInvokeShutdown closes the main thread c#

I am opening a wpf UI in a separate thread using
helperThread = new Thread(() =>
{
//ShowHelpInDialog(e.Url, -1, -1, -1, -1, e.HelpContext);
//System.Windows.Threading.Dispatcher.Run();
dispatcher.Invoke(new Action(() => ShowHelpInDialog(e.Url, -1, -1, -1, -1, e.HelpContext)));
});
helperThread.SetApartmentState(ApartmentState.STA);
helperThread.IsBackground = true;
helperThread.Start();
During dialog close event, I am calling
Dispatcher.CurrentDispatcher.BeginInvokeShutdown(DispatcherPriority.Background);
which is causing main thread/Application to close, Which i don't want.
I don't want my parent application to close.
Please observe the following example on how to open a new Window from another thread:
private void NewWindowHandler(object sender, RoutedEventArgs e)
{
Thread newWindowThread = new Thread(new ThreadStart(ThreadStartingPoint));
newWindowThread.SetApartmentState(ApartmentState.STA);
newWindowThread.IsBackground = true;
newWindowThread.Start();
}
private void ThreadStartingPoint()
{
Window1 tempWindow = new Window1();
tempWindow.Show();
System.Windows.Threading.Dispatcher.Run();
}
From the Multiple Windows, Multiple Threads section of the Threading Model page at MSDN.
UPDATE >>>
This code is 100% tested and will definitely open a new Window in a new thread. If you don't want to shut down the other Window, then don't call the BeginInvokeShutdown method which will shut the Window down. You're calling it on Dispatcher.CurrentDispatcher which is running on the MAIN thread (where the MainWindow.xaml is running).
You would have to invoke BeginInvokeShutdown on the dialog's Dispatcher not on Dispatcher.CurrentDispatcher.
Your dialog closed event handler should look like this:
dialog.Closed += (sender, e) => dialog.Dispatcher.BeginInvokeShutdown();

WPF modal progress window

I apologize if this question has been answered tons of times, but I can't seem to find an answer that works for me. I would like to create a modal window that shows various progress messages while my application performs long running tasks. These tasks are run on a separate thread and I am able to update the text on the progress window at different stages of the process. The cross-thread communication is all working nicely. The problem is that I can't get the window to be on top of only other application windows (not every application on the computer), stay on top, prevent interaction with the parent window, and still allow the work to continue.
Here's what I've tried so far:
First, my splash window is a custom class that extends the Window class and has methods to update the message box. I create a new instance of the splash class early on and Show/Hide it as needed.
In the simplest of cases, I instantiate the window and call .Show() on it:
//from inside my secondary thread
this._splash.Dispatcher.Invoke(new Action(() => this._splash.Show());
//Do things
//update splash text
//Do more things
//close the splash when done
this._splash.Dispatcher.Invoke(new Action(() => this._splash.Hide());
This correctly displays the window and continues running my code to handle the initialization tasks, but it allows me to click on the parent window and bring that to the front.
Next I tried disabling the main window and re-enabling later:
Application.Current.Dispatcher.Invoke(new Action(() => this.MainWindow.IsEnabled = false));
//show splash, do things, etc
Application.Current.Dispatcher.Invoke(new Action(() => this.MainWindow.IsEnabled = true));
This disables all the elements in the window, but I can still click the main window and bring it in front of the splash screen, which is not what I want.
Next I tried using the topmost property on the splash window. This keeps it in front of everything, and in conjunction with setting the main window IsEnabled property I could prevent interaction, but this makes the splash screen appear in front of EVERYTHING, including other applications. I don't want that either. I just want it to be the topmost window within THIS application.
Then I found posts about using .ShowDialog() instead of .Show(). I tried this, and it correctly showed the dialog and did not allow me to click on the parent window, but calling .ShowDialog() makes the program hang waiting for you to close the dialog before it will continue running code. This is obviously, not what I want either. I suppose I could call ShowDialog() on a different thread so that that thread would hang but the thread doing the work would not...is that the recommended method?
I have also considered the possibility of not using a window at all and instead putting a full-sized window element in front of everything else on the page. This would work except that I have other windows I open and I'd like to be able to use the splash screen when those are open too. If I used a window element I would have to re-create it on every window and I wouldn't be able to use my handy UpdateSplashText method in my custom splash class.
So this brings me to the question. What is the right way to handle this?
Thanks for your time and sorry for the long question but details are important :)
You are correct that ShowDialog gives you most of the UI behavior that you want.
It does have the problem that as soon as you call it you block execution though. How could you possibly run some code after you show the form, but define what it should be before it's shown? That's your problem.
You could just do all of the work within the splash class, but that's rather poor practice due to tight coupling.
What you can do is leverage the Loaded event of Window to define code that should run after the window is shown, but where it is defined before you show it.
public static void DoWorkWithModal(Action<IProgress<string>> work)
{
SplashWindow splash = new SplashWindow();
splash.Loaded += (_, args) =>
{
BackgroundWorker worker = new BackgroundWorker();
Progress<string> progress = new Progress<string>(
data => splash.Text = data);
worker.DoWork += (s, workerArgs) => work(progress);
worker.RunWorkerCompleted +=
(s, workerArgs) => splash.Close();
worker.RunWorkerAsync();
};
splash.ShowDialog();
}
Note that this method is designed to encapsulate the boilerplate code here, so that you can pass in any worker method that accepts the progress indicator and it will do that work in a background thread while showing a generic splash screen that has progress indicated from the worker.
This could then be called something like this:
public void Foo()
{
DoWorkWithModal(progress =>
{
Thread.Sleep(5000);//placeholder for real work;
progress.Report("Finished First Task");
Thread.Sleep(5000);//placeholder for real work;
progress.Report("Finished Second Task");
Thread.Sleep(5000);//placeholder for real work;
progress.Report("Finished Third Task");
});
}
The accepted answer from #Servy helped me a lot! And I wanted to share my Version with the async and MVVM approach. It also contains a small delay to avoid "window flickering" for too fast operations.
Dialog Method:
public static async void ShowModal(Func<IProgress<string>, Task> workAsync, string title = null, TimeSpan? waitTimeDialogShow = null)
{
if (!waitTimeDialogShow.HasValue)
{
waitTimeDialogShow = TimeSpan.FromMilliseconds(300);
}
var progressWindow = new ProgressWindow();
progressWindow.Owner = Application.Current.MainWindow;
var viewModel = progressWindow.DataContext as ProgressWindowViewModel;
Progress<string> progress = new Progress<string>(text => viewModel.Text = text);
if(!string.IsNullOrEmpty(title))
{
viewModel.Title = title;
}
var workingTask = workAsync(progress);
progressWindow.Loaded += async (s, e) =>
{
await workingTask;
progressWindow.Close();
};
await Task.Delay((int)waitTimeDialogShow.Value.TotalMilliseconds);
if (!workingTask.IsCompleted && !workingTask.IsFaulted)
{
progressWindow.ShowDialog();
}
}
Usage:
ShowModal(async progress =>
{
await Task.Delay(5000); // Task 1
progress.Report("Finished first task");
await Task.Delay(5000); // Task 2
progress.Report("Finished second task");
});
Thanks again #Servy, saved me a lot of time.
You can use the Visibility property on Window to hide the whole window while the splash screen runs.
XAML
<Window ... Name="window" />
Code
window.Visibility = System.Windows.Visibility.Hidden;
//show splash
//do work
//end splash
window.Visibility = System.Windows.Visibility.Visible;
You can have your progress window's constructor take a Task and then ensure the window calls task.Start on the OnLoaded event. Then you use ShowDialog from the parent form, which will cause the progress window to start the task.
Note you could also call task.Start in the constructor, or in the parent form anywhere before calling ShowDialog. Whichever makes most sense to you.
Another option would be just to use a progress bar in the status strip of the main window, and get rid of the popup. This option seems to be more and more common these days.
I found a way to make this work by calling ShowDialog() on a separate thread. I created my own ShowMe() and HideMe() methods in my dialog class that handle the work. I also capture the Closing event to prevent closing the dialog so I can re-use it.
Here's my code for my splash screen class:
public partial class StartupSplash : Window
{
private Thread _showHideThread;
public StartupSplash()
{
InitializeComponent();
this.Closing += OnCloseDialog;
}
public string Message
{
get
{
return this.lb_progress.Content.ToString();
}
set
{
if (Application.Current.Dispatcher.Thread == System.Threading.Thread.CurrentThread)
this.lb_progress.Content = value;
else
this.lb_progress.Dispatcher.Invoke(new Action(() => this.lb_progress.Content = value));
}
}
public void ShowMe()
{
_showHideThread = new Thread(new ParameterizedThreadStart(doShowHideDialog));
_showHideThread.Start(true);
}
public void HideMe()
{
//_showHideThread.Start(false);
this.doShowHideDialog(false);
}
private void doShowHideDialog(object param)
{
bool show = (bool)param;
if (show)
{
if (Application.Current.Dispatcher.Thread == System.Threading.Thread.CurrentThread)
this.ShowDialog();
else
Application.Current.Dispatcher.Invoke(new Action(() => this.ShowDialog()));
}
else
{
if (Application.Current.Dispatcher.Thread == System.Threading.Thread.CurrentThread)
this.Close();
else
Application.Current.Dispatcher.Invoke(new Action(() => this.Close()));
}
}
private void OnCloseDialog(object sender, CancelEventArgs e)
{
e.Cancel = true;
this.Hide();
}
}

SplashScreen.Close(Timespan.FromMilliseconds(int)) : Is there an Event dispatched at Timespan Complete?

C# WPF Application
I have a SplashScreen being displayed at startup for a minimum amount of time by using
Thread.Sleep(int); //int = milliseconds to display splash screen
When that sleep time is reached, the code resumes and the SplashScreen fades out to close by using
SplashScreen.Close(Timespan.FromMilliseconds(int)); //int = milliseconds fade-out
I would like to pause at this point to wait until the SplashScreen has become 100% transparent and is fully closed, then continue with other tasks, I.E. Writiting to the Console or displaying a MainWindow.
Is there an event fired when the (TimeSpan.FromMilliseconds(int)) is complete?
Any other suggestions?
namespace StartupSplash
{
public class SplashScreenStartup
{
//IMPORTANT:set image property to Resource and NOT Splash Screen
private SplashScreen Splash = new SplashScreen("Resources/SplashScreen.png");
public void SplashScreenStartUp()
{
Splash.Show(false, true);
Thread.Sleep(3000); // Pause code, display splash screen 3 seconds
Splash.Close(TimeSpan.FromMilliseconds(3000)); // 3 second splash fade-out
// I want to wait until splash screen fadeOut has completed before
// this next console output is performed.
Console.WriteLine("Executes before Splash fadeOut completes.");
}
}
Maybe this code can help you. Using the backgroundworker class:
BackgroundWorker worker = new BackgroundWorker();
worker.DoWork += (o, ea) =>
{
// Dispatcher.Invoke commands the dispatcher to do something
Dispatcher.Invoke((Action)(() => Splash.Close(TimeSpan.FromMilliseconds(3000)));
// Sleeps this worker but NOT the UI
Thread.Sleep(3000);
};
worker.RunWorkerCompleted += (o, ea) =>
{
// Open your mainwindow sample
MainWindow w = new MainWindow();
w.Show();
};
//Runs the worker on its own thread
worker.RunWorkerAsync();
This should start the closing of your splashscreen, then sleep through it, and when it's done it'll open your mainwindow. I actually use something very similar to this to implement a login and fetch info for my WPF app, while displaying a progress bar and updating the text in it to stuff like "Connecting to server", "Logging in" and "Fetching data".
I found that the following code works. I am not quite clear why and I will delve in closer to understand this better. Please critique as needed, I am here to learn and share. Cheers.
class Tester
{
// Create splash screen instance and reference the image location.
// IMPORTANT Ensure that the image properties are set to Resource and NOT Splash Screen
private SplashScreen Splash = new SplashScreen("Resources/SplashScreen.png");
public void Display()
{
Splash.Show(false, true);
// pause the code, thus, displaying the splash for 3 seconds
Thread.Sleep(3000);
// close the splash
Close();
}
private void Close()
{
// sets the fadeout time in milliseconds
int fadeOutTime = 1500;
// wait until the splash screen fadeOut has completed before writing to the console
BackgroundWorker worker = new BackgroundWorker();
worker.DoWork += (o, ea) =>
{
// Run background task (fade out and close the splash)
Splash.Close(TimeSpan.FromMilliseconds(fadeOutTime));
// Sleep this worker but NOT the UI (for the same time as the fade out time)
Thread.Sleep(fadeOutTime);
};
worker.RunWorkerCompleted += (o, ea) =>
{
// Execute task after splash has closed completely
Console.WriteLine("This is after the splash screen fadeOut completes.");
};
// start the background task, on it's own thread
worker.RunWorkerAsync();
}
}
I eventually came to conclusion that I was barking up the wrong tree in my previous comments. Displaying the SplashScreen in the background is both problematic (it refused to close automatically, no matter what I tried) and unnessary. Here's what I ended up with... Really simple!
using System;
using System.Net;
using System.Windows;
namespace WpfApplication1
{
/// <summary>
/// Interaction logic for Window1.xaml
/// </summary>
public partial class Window1 : Window
{
public Window1() {
InitializeComponent();
}
private void Window_Loaded(object sender, RoutedEventArgs e) {
// show the splash screen
// nb: Resources/SplashScreenImage.png file Properties ~ Build Action='Resource'
var splashScreen = new SplashScreen("Resources/SplashScreenImage.png");
splashScreen.Show(false); // don't close automatically
// ... initialise my application ...
Initialise();
// close the splash screen.
splashScreen.Close(TimeSpan.FromMilliseconds(250D));
}
private void Initialise() {
// do my long-running application initialisation on the main thread.
// In reality you'd do this download asyncronously, but in this case
// it serves as a simple proxy for some "heavy" inititalisation work.
textBox1.Text = new WebClient().DownloadString("http://stackoverflow.com/questions/13213625/splashscreen-closetimespan-frommilliseconds-listen-for-closed-event");
}
}
}
I hope that helps... though I'm not at all confident that it will ;-)
Cheers. Keith.
PS: I wonder why the splash refused to close? My guess it internally relies on events which are only available (i.e. subscribable) on WPF's equivalent of the event-dispatch-thread (whatever it's called).
I never did find an event to listen for upon completion of the TimeSpan. Also, after deciding to Not stop the threads, I chose to use DispatcherTimers instead.
(I have thinned and contained the logic into this one class for reference purposes)
using System;
using System.Windows;
using System.Windows.Threading;
namespace StartupSplash2
{
public partial class MainWindow : Window
{
private DispatcherTimer visibleTimer;
private DispatcherTimer fadeoutTimer;
private SplashScreen splash;
private int visibleTime = (4000); //milliseconds of splash visible time
private int fadeoutTime = (1500); //milliseconds of splash fadeout time
public MainWindow()
{
//hide this MainWindow window until splash completes
this.Visibility = Visibility.Hidden;
InitializeComponent();
splashIn(); //start the splash
}
private void splashIn()
{
splash = new SplashScreen("Resources/SplashScreen.png"); //ensure image property is set to Resource and not screen saver
visibleTimer = new DispatcherTimer(); //timer controlling how long splash is visible
visibleTimer.Interval = TimeSpan.FromMilliseconds(visibleTime);
visibleTimer.Tick += showTimer_Tick; //when timer time is reached, call 'showTimer_Tick" to begin fadeout
splash.Show(false, true); //display splash
visibleTimer.Start();
}
private void showTimer_Tick(object sender, EventArgs e)
{
visibleTimer.Stop();
visibleTimer = null; //clear the unused timer
fadeoutTimer = new DispatcherTimer();
fadeoutTimer.Interval = TimeSpan.FromMilliseconds(fadeoutTime); //a timer that runs while splash fades out and controlls when main window is displayed
fadeoutTimer.Tick += fadeTimer_Tick; //when fadeout timer is reached, call 'fadeTimer_Tick' to show main window
splash.Close(TimeSpan.FromMilliseconds(fadeoutTime)); //begin splash fadeout to close
fadeoutTimer.Start();
}
private void fadeTimer_Tick(object sender, EventArgs e)
{
fadeoutTimer.Stop();
fadeoutTimer = null; //clear the unused timer
splash = null; //clear the splash var
MainWindowReady(); //call method to display main window
}
public void MainWindowReady()
{
this.Visibility = Visibility.Visible;
//Here is the start of the Main Window Code
this.Content = "Ok, the app is ready to roll";
}
}
}
I found an event called SplashScreen.Dismissed that allows you to start the app after the SplashScreen expires. However, minimum required OS is Windows 8 and I could not use it.
More info can be found here MSDN

Categories