Prism Splash Screen Module

Splash screen is a good thing. It makes your application looks professional while numbers of libraries are being loaded in the background, mean while, users may feel the loading time is actually not that long if they see something updating. So the way we designing a splash screen is indeed very important in terms of a good one.

There’re various ways you can find everywhere to implement a splash screen but very few of them meet my criteria of good ones:

  • A splash screen should provide status updating to prove the application is not hung
  • A splash screen should show as the first visual of the application, especially, the main window should only be visible after the splash screen is gone – which means the initialization process has finished
  • A splash screen should be interactable – Some applications like to show splash screen as topmost – users can’t bring their other stuff to front if it’s overlapped by the splash; A lot of applications’ splash screen is not moveable, what if it happens to be topmost? Some applications has status updates on the splash screen but when you click on it, Windows tends to tell you the application window is busy, even worse, the window is frozen and not responding.
  • A better splash screen should give user more options: either allow them to close it (by double clicking it for example), or allow them drag and move the splash screen around without freeing the window if user still want to see the status updating

Today I’ll introduce one neat approach of implementing a splash screen that meet all of the above criteria, in a MVVM manner, in Prism. Prism is such a good application framework that makes your application modulized naturally, therefore it’s also an intuitive thinking that we can make splash screen a module, so it’s independent to other modules and can be easily reused in future applications.

Ok, seems having said too much :), let’s go to the implementation.

Usually in the unity bootstrapper, we create the shell and show it, like this:

public class Bootstrapper : UnityBootstrapper
{
  protected override DependencyObject CreateShell()
  {
    var shell = Container.Resolve<IShell>();
    shell.Show();
    return shell as DependencyObject;
  }
}

The first thing to do is to create the shell but not showing it – instead we let the splash screen module to do that (through the Show() method of the IShell interface) as we don’t want the shell to be visible before all module loadings are finished.

The splash screen’s Module class will be like this:

public class Module : IModule
{
  public Module(IUnityContainer container_, IEventAggregator eventAggregator_, IShell shell_)
  {
    Container = container_;  //we need the unity container to register and resolve types
    EventAggregator = eventAggregator_;  //we need the event aggregator for interactions between splash screen and the shell
    Shell = shell_;  //we need the shell as it's the splash screen's responsibility to show it
  }
}

Before we move on, one more thing need to be changed is the number of instances of the IShell type, obviously only one instance is needed otherwise the one the Module class above get will be a new unexpected instance. So the BootStrapper will be like this:

public class Bootstrapper : UnityBootstrapper
{
  protected override void ConfigureContainer()
  {
    Container.RegisterType<IShell, Shell>(new ContainerControlledLifetimeManager());
    base.ConfigureContainer();
  }

  protected override DependencyObject CreateShell()
  {
    var shell = Container.Resolve<IShell>();
    return shell as DependencyObject;
  }
}

Next is how do we implement the splash. Double click to close and drag move is easy, two lines of code like below will do (but you better do it in a attached behavior for reuse).

  splash.MouseDoubleClick += (s_, e_) => splash.Close();
  splash.MouseLeftButtonDown += (s_, e_) => splash.DragMove();

Hard part is the interactivity, and the proposed way is to start the splash screen in a separate STA thread and communicate with other modules through EventAggregator, in this way you won’t bother with the responsiveness. Then finally the sequence of the communication is:

  1. Create the shell but don’t show it
  2. Initialize the modules by starting with the splash screen module
  3. The splash screen module will queue a request on the Shell’s dispatcher, create a new STA thread to show the splash screen, subscribe to the MessageUpdateEvent and return.
  4. Keep initialize other modules and publish the status through the MessageUpdateEvent so the splash screen can show it (publishing of the status can also be done by each module to make the bootstrapper cleaner)
  5. After the initialization is done, the request queued on the dispatcher get called, so the Shell shows up and we close the splash screen and shut down the STA thread we created for it.

Sample project download: PrismSplash.zip

Advertisements

About eagleboost

Investment Bank senior software developer
此条目发表在WPF分类目录,贴了, , , 标签。将固定链接加入收藏夹。

2 Responses to Prism Splash Screen Module

  1. Peter说道:

    This project uses an outdated version of PRISM. Is using the older composite libraries.

  2. eagleboost说道:

    It’s been a while so the version is problably outdated. Do you see any problem when running this sample against the latest Prism library?

发表评论

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / 更改 )

Twitter picture

You are commenting using your Twitter account. Log Out / 更改 )

Facebook photo

You are commenting using your Facebook account. Log Out / 更改 )

Google+ photo

You are commenting using your Google+ account. Log Out / 更改 )

Connecting to %s