2010-09-02 15 views
5

Ho una pagina all'interno di un'applicazione di navigazione in stile WPF che mostra i risultati della ricerca. La pagina contiene diversi controlli con associazione a dati. La pagina stessa funziona bene; esegue la ricerca e restituisce risultati. I controlli CheckBox associati a dati funzionano correttamente.Associazione dati WPF MVVM interrotta dopo l'esplorazione della pagina

Ma se faccio clic su un collegamento risultato e poi sul pulsante Indietro per tornare all'elenco dei risultati, tutti i miei binding dati CheckBox.IsChecked sono interrotti. Altri controlli associati ai dati (ComboBox, DatePickers, ecc.) Continuano a funzionare come previsto. Il binding con altre proprietà sul controllo CheckBox, come IsEnabled, funziona correttamente. Ma il binding IsChecked rimane interrotto finché non aggiorno la pagina.

Ecco il XAML utilizzato per uno dei miei controlli CheckBox:

<CheckBox IsChecked="{Binding IncludeNote}" Content="Note" IsEnabled="{Binding IsBusy, Converter={StaticResource boolNot}}" /> 

Come si può vedere, non c'è niente di speciale succedendo qui. Ma dopo aver spostato l'app WPF in avanti o indietro alla pagina, l'associazione IsChecked verrà interrotta mentre la proprietà continuerà a funzionare.

Cosa sta succedendo qui? è un insetto?

UPDATE: Dopo aver giocato con alcune alternative, ho scoperto che questo problema riguarda anche il controllo ToggleButton, da cui deriva CheckBox.

UPDATE2: Ed è anche danneggiato per la proprietà TextBox.Text.

C'è un modo per "aggiornare" i binding di dati per questi controlli? O dovrei prendere qualche altro approccio per risolvere questo problema?

risposta

5

Apparentemente, lo è un errore. Ecco la segnalazione di bug su Microsoft Connect: Binding does not work after back/forward navigation.

L'utente che ha segnalato il bug, RQDQ, ha anche ricordato il suo approccio per affrontare il problema:

La soluzione che ho trovato è quello di chiamare manualmente BindingOperations.SetBinding per tutte le associazioni nella pagina durante la Evento caricato Questo sembra funzionare se si naviga in modo esplicito o tramite cronologia (operazioni indietro/avanti).

Questo è solo un problema in WPF4. Il binding dei dati funziona come previsto in .NET 3.5.

Spero che Microsoft risolva questo rapidamente. Questo è un problema serio per le app WPF in stile navigazione.

0

Una soluzione semplice è impostare KeepAlive su true e quindi per garantire che non vi siano problemi con VIewModel che presenta uno stato non valido da un caricamento della pagina precedente, DataContext viene impostato su una nuova istanza ogni volta nell'evento Loaded (ad esempio non associare a un'istanza di ViewModel nel tuo Page.Resources dictionary, ad esempio, poiché verrà mantenuto).

Un approccio standard che usiamo per legare la pagina al modello di vista è con un semplice comportamento collegato alla pagina.

public sealed class PageViewModelBehavior : Behavior<Page> 
{ 
    public Type DataType { get; set; } 

    protected override void OnAttached() 
    { 
     this.AssociatedObject.KeepAlive = true; 
     this.AssociatedObject.Loaded += this.AssociatedObjectLoaded; 
     this.AssociatedObject.Unloaded += this.AssociatedObjectUnloaded; 
     base.OnAttached(); 
    } 

    protected override void OnDetaching() 
    { 
     this.AssociatedObject.Unloaded -= this.AssociatedObjectUnloaded; 
     this.AssociatedObject.Loaded -= this.AssociatedObjectLoaded; 
     base.OnDetaching(); 
    } 

    private void AssociatedObjectLoaded(object sender, RoutedEventArgs e) 
    { 
     if (this.DataType == null || !typeof(IPageViewModel).IsAssignableFrom(this.DataType)) 
     { 
      throw new InvalidOperationException("PageViewModelBehavior.DataType is not set. Page: " + this.AssociatedObject.GetType().Name); 
     } 

     this.AssociatedObject.DataContext = Activator.CreateInstance(this.DataType); 

     // TODO: Call load on your page view model etc. 
    } 


    private void AssociatedObjectUnloaded(object sender, RoutedEventArgs e) 
    { 
     // TODO: Call unload on your page view model etc. 

     // Allow the throw-away view model to be GC'd 
     this.AssociatedObject.DataContext = null; 
    } 
} 

In questo modo la pagina viene associata di nuovo ogni volta che l'utente torna alla pagina.Ciò consente inoltre di utilizzare il contenitore IOC preferito per creare ViewModel.

+0

Il problema più grande qui è che può causare rapidamente una perdita di memoria (s). – ouflak