DarioSantarelli.Blog("UgiDotNet");

<sharing mode=”On” users=”*” />
posts - 176, comments - 144, trackbacks - 3

My Links

News


This is my personal blog. These postings are provided "AS IS" with no warranties, and confer no rights.

logo linkedIn logo Twitter logo FaceBook logo RSS logo Email

Logo DotNetMarche
Logo XPUG Marche



Tag Cloud

Archives

Post Categories

My English Blog

domenica 30 maggio 2010

[WPF] MVVM e Splash Screen

Durante lo sviluppo di applicazioni WPF di una certa “pesantezza”, può essere utile ricorrere a Splash Screen aggiornabili in tempo reale che notifichino all’utente lo stato di avanzamento del caricamento dei vari moduli, ad esempio tramite elementi di testo piuttosto che barre di progresso. A volte, infatti, può non essere sufficiente una semplice immagine impostabile tramite la Build Action "SplashScreen" di Visual Studio.
In questo post vorrei quindi mostrare una possibile implementazione di uno Splash Screen aggiornabile in tempo reale usando il pattern MVVM. 

Per semplificare, supponiamo di posizionare nel Main la pesantissima sequenza di caricamento della nostra applicazione:

public static class Program
{
 
[STAThread]
 
public static void Main(string[] args)
 
{
   
App app = new App();
   
app.InitializeComponent();  // Load resources...           

    MainWindow mainWindow = null;
   
using (SplashScreenViewModel splashScreenViewModel = SplashScreen.ShowSplashScreen())
   
{
     
splashScreenViewModel.StatusText = "Initializing..."
                 
     // Loading application modules...
      Thread.Sleep(3000); // Simulate delay... 

      mainWindow = new MainWindow();

       splashScreenViewModel.StatusText = "Initialized."
      Thread.Sleep(1000);
  
           

     app.Run(mainWindow);
 
}       
}


Al fine di evitare fastidiosi effetti di freezing della GUI mentre il thread principale sta caricando i vari pezzi della nostra applicazione, la window dello Splash Screen va fatta girare necessariamente su un thread separato. Al termine della sequenza di caricamento, il thread principale deve poter chiudere lo Splash Screen utilizzando il Dispatcher corretto.
Vediamo quindi il codice della view:

public partial class SplashScreen : Window
{
 
private static object splashScreenlockObj = new object();  

  public SplashScreen()
 
{
   
InitializeComponent(); 
    DataContext = new SplashScreenViewModel();
 
}

   public static SplashScreenViewModel ShowSplashScreen()
 
{
   
lock (splashScreenlockObj)
   
{
    
SplashScreenViewModel splashScreenViewModel = null
     ManualResetEvent resetEvent = new ManualResetEvent(false);

     Thread splashScreenThread = new Thread(() =>
    
{
      
Dispatcher.CurrentDispatcher.BeginInvoke((Action)delegate() 
      
{
        
SplashScreen splashScreenWindow = new SplashScreen();
        
splashScreenViewModel = (SplashScreenViewModel)splashScreenWindow.DataContext;
        
splashScreenViewModel.Dispatcher = Dispatcher.CurrentDispatcher;
        
resetEvent.Set();
        
splashScreenWindow.Show(); 
      
});
      
Dispatcher.Run();

      });

              splashScreenThread.SetApartmentState(ApartmentState.STA);
     
splashScreenThread.IsBackground = true
     
splashScreenThread.Start();

      resetEvent.WaitOne(); // Wait for viewmodel initialization...

     
return splashScreenViewModel;
   
}
 
}
}

Il metodo statico ShowSplashScreen() visualizza lo splash screen e comunica al ViewModel quale Dispatcher utilizzare per la chiusura (InvokeShutdown()).

public class SplashScreenViewModel : ViewModelBase, IDisposable
{
 
private string _statusText = null;
 
public string StatusText
 
{
   
get { return _statusText; }
   
set
   
{
     
if (_statusText == value) return
      _statusText = value;
     
OnPropertyChanged("StatusText");
   
}
  
}

 
public Dispatcher Dispatcher { get; set; }

 
public void Dispose()
 
{
   
if (Dispatcher != null)
   
{
     
Dispatcher.InvokeShutdown();
     
Dispatcher = null;
   
}
 
}
}

 

Technorati Tag: ,

posted @ domenica 30 maggio 2010 21.36 | Feedback (5) | Filed Under [ WPF ]

Powered by: