2011-10-01 17 views
7

Scrivo un'app che mostra un elenco del tempo rimanente in corso su un utente. Voglio che l'elenco si aggiorni dinamicamente ogni secondo in modo che l'utente abbia la panoramica completa.ViewModel si aggiorna ogni secondo?

public class ReservationCustomerList : INotifyPropertyChanged 
{ 
    public int UnitsLeft { get; set; } 
    public DateTime? OnCircuitSince { get; set; } 
    public TimeSpan? TimeLeftDate 
    { 
     get 
     { 
      if (OnCircuitSince.HasValue) 
       return TimeSpan.FromSeconds((OnCircuitSince.Value - DateTime.Now).TotalSeconds - UnitsLeft); 
      return TimeSpan.FromSeconds(UnitsLeft); 
     } 
    } 
    private void FireEverySecond() 
    { 
     PropertyChanged.Fire(this, x => x.TimeLeftDate); 
    } 
} 

Come potete vedere sopra l'idea è che il modello sa quando il cliente è entrato nel circuito e il tempo l'hanno lasciato. Come si può vedere iam pensando di usare l'interfaccia INotifyPropertyChanged e quindi di avere un timer su ogni viewmodel.

Tuttavia questa è la mia preoccupazione. L'aggiunta di un timer su ogni viewmodel sembra molto gonfia, questo è davvero il modo migliore per ottenere questo? La seconda preoccupazione è che se il timer non viene mai fermato, non si verificherebbe una perdita di memoria dal momento che il timer non si fermerebbe mai e manterrà vivo il viewmodel? Se questo è il mio Viewmodel dovrebbe anche implementare IDisposable e dovrei ricordarmi di scorrere tutti i viewmodels e disporli per assicurarmi che questi siano dati inutili. Le mie preoccupazioni sono corrette?


Grazie.

Sì, stavo pensando di avere un servizio di timer per evitare di avere più timer, tuttavia dover annullare la registrazione manualmente avrebbe sicuramente a un certo punto introdurre perdite di memoria.

Quindi l'idea con Weak Events è ottima.

pensare Iam di fare qualcosa di simile:

public class TimerService 
{ 
    static Timer Timer; 
    static FastSmartWeakEvent<EventHandler> _secondEvent = new FastSmartWeakEvent<EventHandler>(); 
    static FastSmartWeakEvent<EventHandler> _minuteEvent = new FastSmartWeakEvent<EventHandler>(); 
    static DateTime LastTime; 
    public static event EventHandler SecondEvent 
    { 
     add { _secondEvent.Add(value); } 
     remove { _secondEvent.Remove(value); } 
    } 
    public static event EventHandler MinuteEvent 
    { 
     add { _minuteEvent.Add(value); } 
     remove { _minuteEvent.Remove(value); } 
    } 
    static TimerService() 
    { 
     Timer = new Timer(TimerFire, null, 1000, 1000); 
    } 
    static void TimerFire(object state) 
    { 
     _secondEvent.Raise(null, EventArgs.Empty); 
     if (LastTime.Minute != DateTime.Now.Minute) 
      _minuteEvent.Raise(null, EventArgs.Empty); 
     LastTime = DateTime.Now; 
    } 
} 

Avete un commento? So che potrei usare un singleton GetInstance (o IoC), ma questo lo renderebbe più incongruo da usare.

Iam utilizza l'implementazione di WeakEvent che Daniel Grunwald ha scritto su codeproject. (dà una classe molto pulita e non troppo in alto). http://www.codeproject.com/KB/cs/WeakEvents.aspx

+0

Soluzione piacevole. Se si utilizza MEF o simili, è possibile mantenere un'istanza del servizio nel contenitore anziché utilizzare metodi statici. In caso contrario, allora consiglierei di renderlo un singleton. Avere un'istanza invece di metodi statici è meglio per il test. – alf

risposta

7

Si potrebbe avere un servizio di timer con un timer privato e un evento pubblico, che notifica tutti i modelli di visualizzazione ogni secondo.

Per quanto riguarda i problemi di memoria, è possibile registrare il ViewModel con il servizio timer quando la pagina è navigabile (OnNavigatedTo) e annullare la registrazione quando la vista è chiuso (OnNavigatedFrom). In questo modo i viewmodels non avrebbero alcun riferimento con il servizio timer quando escono dall'ambito di applicazione e sarebbero raccolti in modo corretto.

+4

Per supportare questo modello, consultare [l'articolo MSDN sui modelli di evento deboli] (http://msdn.microsoft.com/en-us/library/aa970850.aspx) –

+4

È inoltre possibile utilizzare EventAggregator dal framework Prism: http://msdn.microsoft.com/en-us/library/ff921122(v=pandp.20).aspx – Ucodia

Problemi correlati