Ricordare la posizione delle Window di WPF usando MVVM
Una delle caratteristiche che trovo simpatiche in un’applicazione Windows è quando si ricorda la posizione e la dimensione delle finestre. Questa cosa diventa ancora più utile se si utilizza più di un monitor, perchè a questo punto la nostra applicazione si ricorderà di aprire le finestre anche sull’eventuale monitor secondario, ridimensionate e nella stessa identica posizione in cui la avevamo lasciate l’ultima volta.
Fare questa cosa con il code-behind è piuttosto banale, perchè basta gestire gli eventi Closed e Loaded delle finestre: nel primo caso bisogna salvare da qualche parte posizione e dimensione, nel secondo caso bisogna leggerle e ripristinarle.
E se volessi implementare questo meccanismo in un’applicazione enterprise sviluppata con MVVM? Magari scrivendo un codice XAML di questo tipo:
<Window x:Class="AppDiProva.UI.WPF.Views.LoginWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:helper="clr-namespace:Helpers.Xaml" Title="Titolo" Height="370" Width="500" ResizeMode="NoResize" helper:WindowStateHelper.Active="True"> </Window>
Ho volutamente lasciato una riga spaziata per evidenziare l’helper che utilizzo, e che ovviamente mi sono scritto per gestire questo scenario. In pratica, si tratta di una classe WindowStateHelper, con una sola dependency property booleana, che imposto a “True”. Quando viene attivata, come nell’esempio qui sopra, internamente fa tutto quanto il lavoro, che può essere riassunto così:
- sottoscrive gli eventi Closed e Loaded della Window
- quando una finestra viene chiusa, salvo in un semplice file di testo la dimensione e la posizione della finestra; il nome del file viene generato prendendo in pratica il nome della classe, sostituendo ogni “.” con “-“, giusto per rendere il nome del file gradevole. Quindi lo stato di una Window con nome VivendoByte.MioSoftware.UI.LoginWindow verrebbe salvato nel file “VivendoByte-MioSoftware-UI-LoginWindow.txt”
- quando una finestre viene riaperta, controllo se esiste un file che contiene il suo stato (prendo il nome della classe, come nel punto 2): se esiste, lo leggo e lo decodifico, e reimposto dimensione e posizione. Se non esiste, significa che è la prima volta che è stata aperta, per cui non faccio nulla
- I files vengono salvati nella directory Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + "\Mio Programma\"; evitate la cartella di roaming, perchè in questo modo andreste a sincronizzare i files sugli altri PC con cui vi loggate con lo stesso Microsoft Account. E quindi significa che se su un PC avete due monitor Full HD, e su un notebook avete una vetusta 1366×768, le finestre potrebbero non comparire perchè al di fuori dell’area visibile
Lo trovo piuttosto elegante, e soprattutto molto trasparente, perchè il developer finale dell’applicazione non si accorge di nulla. Lui sa che lo stato delle finestre viene salvato e ripristinato, e tanto basta, senza troppe complicazioni e concentrandosi sulla sua applicazione finale.
Il codice dell’helper è scaricabile da qui. E’ sicuramente migliorabile, ma è un buon punto di partenza.