Ciao.
Ho un dubbio sul da farsi; il problema in se e per se l'avrei anche risolto, ma non so se sia l'approccio corretto.
Sto sviluppando un'App per UniversalApp, con Caliburn Micro 2.
Ho una lista di oggetti che potrebbero cambiare il loro stato di minuto in minuto, passando da uno stato "disponibile" ad uno "scaduto", in base al fatto che l'orario impostato sia o meno stato superato, una cosa del tipo:
public class MioOggettoConScadenza{
[...]
public Disable { 
{
 get{
   return this.MyTime.TimeOfDay > DataTime.Now.TimeOfDay;
  }
}
}


Nel ViewModel ho una lista simile a questa:
var miaLista = new ObservableCollection<MioOggettoConScadenza>();

Vorrei usare il DispatcherTimer per forzare l'aggiornamento del Binding, visto che di minuto in minuto lo stato Disable può cambiare.

La soluzione che ho trovato è ciclare sugli elementi XAML collegati alla lista e fare come da msdn:

private void dispatcherTimer_Tick(object sender, EventArgs e) {
  foreach (var mioElem in XamlElements){ //XamlElements rappresent gli elementi in binding creati in una ListView a runtime e ognuno collegato con DataContext impostato ad un'istanza di MioOggettoConScadenza
    BindingExpression be = mioElem.GetBindingExpression(mioElem.MiaProperty);
    be.UpdateTarget();
  }
}

Probabilmente questa soluzione funziona, ma non mi convince... dato che la proprietà implementa INotifyPropertyChanged vorrei scatenare l'update dal ViewModel e non dalla view; ho pensato di creare un metodo pubblico negli oggetti MioOggettoConScadenza tipo questo:
public async Task ForseUpdateDisable(){
  NotifyOfPropertyChanged(() => Disable );
}

e quindi nel BM fare
private void dispatcherTimer_Tick(object sender, EventArgs e) {
  foreach (var elem in miaLista){
    elem.ForseUpdateDisable(); // Non credo serva await, anzi
  }
}


Entrambe le soluzioni non mi fanno impazzire, ma forse mi sto complicando la vita...

Le domande:
1) Qual'è l'approccio migliore fra i 2 ? In caso entrambe le soluzioni facciano schifo, alternativa?
2) E' la prima volta che utilizzo la classe DispatcherTimer: è lo strumento corretto da utilizzare oppure no? Rischio dei blocchi della UI?

Lorenzo
***
http://blog.lorenzospace.com
37 messaggi dal 16 giugno 2011
Contributi
Ciao,


Vorrei usare il DispatcherTimer per forzare l'aggiornamento del Binding, visto che di minuto in minuto lo stato Disable può cambiare.


Se come dici tu sono già in binding, non c'è bisogno di forzarli. Infatti basterà una chiamata a NotifyOfPropertyChanged e la lista degli oggetti cambierà automaticamente sia nel ViewModel che nello XAML.

Questo ti dovrebbe evitare l'uso del DispatcherTimer, che sebbene non blocchi la UI (perché come dice il nome gira su un thread separato), aiuta a tenere l'applicazione più leggera.
Ciao,

grazie per la risposta; alla fine avevo optato per il timer nel VW:
timer = ThreadPoolTimer.CreatePeriodicTimer(async (e) =>
            {              
                foreach (var oggettoCheCambia in MieiOggettiCheCambianto)
                {
                    await oggettoCheCambia.UpdateTimerAsync();
                }
            },
                TimeSpan.FromSeconds(1));


il timer cicla su tutto gli oggetti della collection e per ognuno chiama il meodo UpdateTiimerAsync, che è fatto in questo modo:
public async Task UpdateTimerAsync()
        {
            NotifyOfPropertyChange(()=> RemainingTime);
            NotifyOfPropertyChange(() => Disable);
            NotifyOfPropertyChange(() => TimeExpired);
        }


Il timer serve comunque per richiamare ogni tot (in questo caso ogni secondo) il meotodo UpdateTimerAsync().

Lorenzo

Lorenzo
***
http://blog.lorenzospace.com

Torna al forum | Feed RSS

ASPItalia.com non è responsabile per il contenuto dei messaggi presenti su questo servizio, non avendo nessun controllo sui messaggi postati nei propri forum, che rappresentano l'espressione del pensiero degli autori.