2014-02-25 123 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