2014-02-25 80 views

回答

9

这是我做这个的方案。我这样做的动机是我不想在UI线程上运行初始化代码,并且通常我需要在我的App类(不是Splash屏幕)上的初始化代码。

基本上,我将应用程序StartupUri设置为我的启动画面,从而使球滚动。

在启动画面上,我在应用程序上调用委托。这是在工作线程上运行的。在启动画面中,我处理EndInvoke,并关闭窗口。

在应用程序初始化委托中,我做了工作,最后创建并打开了正常的主窗口。在工作负载期间,我也在Slash上​​有一个方法,允许我更新进度。 OK,代码非常短,并且不包括主窗口代码(不受所有这些影响),但它会与匿名代表一起玩耍并潜水,因此请仔细阅读,并理想地在其中播放调试器。

下面是代码....

<Application x:Class="SplashScreenDemo.App" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    StartupUri="Splash.xaml"> 
    <Application.Resources> 

    </Application.Resources> 
</Application> 

应用程序代码背后...

internal delegate void Invoker(); 
public partial class App : Application 
{ 
    public App() 
    { 
     ApplicationInitialize = _applicationInitialize; 
    } 
    public static new App Current 
    { 
     get { return Application.Current as App; } 
    } 
    internal delegate void ApplicationInitializeDelegate(Splash splashWindow); 
    internal ApplicationInitializeDelegate ApplicationInitialize; 
    private void _applicationInitialize(Splash splashWindow) 
    { 
     // fake workload, but with progress updates. 
     Thread.Sleep(500); 
     splashWindow.SetProgress(0.2); 

     Thread.Sleep(500); 
     splashWindow.SetProgress(0.4); 

     Thread.Sleep(500); 
     splashWindow.SetProgress(0.6); 

     Thread.Sleep(500); 
     splashWindow.SetProgress(0.8); 

     Thread.Sleep(500); 
     splashWindow.SetProgress(1); 

     // Create the main window, but on the UI thread. 
     Dispatcher.BeginInvoke(DispatcherPriority.Normal, (Invoker)delegate 
     { 
      MainWindow = new Window1(); 
      MainWindow.Show(); 
     });   
    } 
} 

飞溅xaml(实际上,没有什么太有趣了这里...)

<Window x:Class="SplashScreenDemo.Splash" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Title="Splash" Height="300" Width="300"> 
    <Grid> 
     <TextBlock Height="21" Margin="91,61,108,0" VerticalAlignment="Top">Splash Screen</TextBlock> 
     <ProgressBar Name="progBar" Margin="22,122,16,109" Minimum="0" Maximum="1"/> 
    </Grid> 
</Window> 

飞溅代码隐藏...

public partial class Splash : Window 
{ 
    public Splash() 
    { 
     InitializeComponent(); 
     this.Loaded += new RoutedEventHandler(Splash_Loaded); 
    } 

    void Splash_Loaded(object sender, RoutedEventArgs e) 
    { 
     IAsyncResult result = null; 

     // This is an anonymous delegate that will be called when the initialization has COMPLETED 
     AsyncCallback initCompleted = delegate(IAsyncResult ar) 
     { 
      App.Current.ApplicationInitialize.EndInvoke(result); 

      // Ensure we call close on the UI Thread. 
      Dispatcher.BeginInvoke(DispatcherPriority.Normal, (Invoker)delegate { Close(); }); 
     }; 

     // This starts the initialization process on the Application 
     result = App.Current.ApplicationInitialize.BeginInvoke(this, initCompleted, null); 
    } 

    public void SetProgress(double progress) 
    { 
     // Ensure we update on the UI Thread. 
     Dispatcher.BeginInvoke(DispatcherPriority.Normal, (Invoker)delegate { progBar.Value = progress; });   
    } 
} 

由于工作是在工作线程上完成的,所以进度条将会很好地更新,并且您在启动画面上拥有的任何动画都将保持娱乐的连续性。

+0

因此,您初始化的所有内容都存储在全局变量中? –

+0

(Invoker)不适合我,但用“new Action(delegate()”替换它 –

+3

以下划线开头的方法声明......真的吗? – Slugart