2012-01-01 10 views
5

Sto lavorando per confrontare due versioni di un listview, per un modulo di impostazioni. Devo sapere se l'utente ha effettivamente modificato l'elenco, nel qual caso quando fanno clic su "Salva", effettivamente salverò. Se non hanno cambiato nulla, quando fanno clic su "Salva" non sprecherò la memoria/tempo ri-salvando qualcosa che non è cambiato.Confronto di due ObservableCollection per vedere se sono diversi

In ogni caso, come posso confrontare due ObservableCollections per vedere se sono affatto diversi?

Grazie in anticipo!

risposta

1

Il modo in cui gestiamo questo richiede un po 'più di lavoro in anticipo, ma può essere automatizzato utilizzando macro VS o strumenti di code-gen come CodeSmith.

Tuttavia, questo approccio è estendibile a qualsiasi costrutto dell'interfaccia utente a cui la raccolta è vincolata e non deve essere reimplementata nell'interfaccia utente ogni volta che è necessario sapere se ci sono o meno modifiche.

Il concetto è di aggiornare i flag all'interno della raccolta e dell'oggetto business per determinare se l'appartenenza alla raccolta è stata modificata o se un determinato record è stato modificato all'interno della raccolta.

L'applicazione è abbastanza semplice:

aggiunge una proprietà HasChanged alla classe di oggetti di business.

Aggiungere una proprietà AnyDeleted alla raccolta. Questo verrà impostato solo se gli elementi vengono eliminati dalla raccolta.

Inizializzare questi valori su falso dopo che i record sono stati letti dal DB.

(Ora la parte semi-noiosa) Per ogni proprietà della classe, impostare la proprietà HasChanged su true se il valore effettivamente cambia. Fai attenzione ai valori nulli. Per esempio:

public bool IsSelected 
    { 
     get 
     { 
      return m_fIsSelected; 
     } 
     set 
     { 
      if (m_fIsSelected != value) 
      { 
       this.HasChanged = true; 
       m_fIsSelected = value; 
      } 
     } 
    } 

modificare l'insieme per impostare la proprietà AnyDeleted true quando un record viene eliminato:

protected override void RemoveItem(int index) 
    { 
     this.AnyDeleted = true; 

     base.RemoveItem(index); 
    } 

Infine, aggiungere un metodo per la raccolta di indicare se nulla è cambiato. Questo è il metodo che si chiamerà per determinare se eventuali modifiche devono essere salvati:

public bool HasAnyChanges() 
    { 
     // Exceptions are handled by the caller 

     // If anything was deleted, return true 
     if (this.AnyDeleted) 
     { 
      return true; 
     } 
     else 
     { 
      foreach (T theItem in this) 
      { 
       if (theItem.HasAnyChanges()) 
       { 
        return true; 
       } 
      } 
     } 

     return false; 
    } 
0

Edit:

void ListView_ItemInserted(Object sender, ListViewInsertedEventArgs e) 
    { 
    if (e.Exception == null) 
    { 
     if (e.AffectedRows > 0) 
     { 
     flag = True; 
     } 
     else 
     { 
     flag = False; 
     } 
    } 

void ListView_Itemdeleted(Object sender, ListViewDeletedEventArgs e) 
    { 
    if (e.Exception == null) 
    { 
     if (e.AffectedRows > 0) 
     { 
     flag = True; 
     } 
     else 
     { 
     flag = False; 
     } 
    } 


void ListView_ItemUpdated(Object sender, ListViewUpdatedEventArgs e) 
    { 
    if (e.Exception == null) 
    { 
     if (e.AffectedRows > 0) 
     { 
     flag = True; 
     } 
     else 
     { 
     flag = False; 
     } 
    } 

è possibile controllare questa variabile bandiera prima di salvare. Questo dovrebbe fare! se è vero, salvalo!

+0

Non c'è due listviews, in realtà, uno solo. – mattsven

+0

la tua domanda indica due versioni di listview! Quindi cosa intendi con questo? Hai di nuovo menzionato sul confronto di due! – King

+0

Si sta vincolando un listview in una struttura di dati come xml o averlo come stringa e quindi salvarlo nelle impostazioni? È così ? @NeXXeuS Se capisco che la tua domanda sia così. Quindi, a meno che l'applicazione non abbia le impostazioni in memoria e la aggiorna continuamente, dovresti leggere le impostazioni e farlo. È tanto quanto salvarlo. Non penso che farebbe la differenza in termini di prestazioni, se è così. – King

4

È possibile utilizzare il metodo LINQ Tranne: produce la differenza di set di due sequenze.

http://msdn.microsoft.com/en-us/library/system.linq.enumerable.except.aspx

Si consideri il seguente metodo di esempio ...

public void ExceptFunctioni() 
{ 
    int[] numbersA = { 0, 2, 4, 5, 6, 8, 9 }; 
    int[] numbersB = { 1, 3, 5, 7, 8 }; 
    IEnumerable<int> aOnlyNumbers = numbersA.Except(numbersB); 
    if(aOnlyNumbers.Count()>0) 
    { 
     // do something 
    } 
} 

Il Tranne metodo viene richiamato sulla prima collezione e ha superato la seconda collezione come argomento. Il risultato conterrà le differenze. È quindi possibile interrogare il risultato e agire di conseguenza. Se entrambe le sequenze sono uguali, il conteggio del risultato sarà zero.

Detto questo, è degno di nota che la strategia preferita nel mondo MVVM sarebbe quella di utilizzare questo metodo per controllare se il pulsante "Salva" è abilitato o meno. In questo approccio, se le due raccolte sono uguali, il pulsante "Salva" verrà disabilitato e l'utente non potrà accedervi.

Ma in entrambi i casi, il metodo LINQ offre un modo molto condensata di realizzare quello che stai dopo ...

AGGIUNTA: vedendo i commenti che hai fatto in risposta al commento 'di Dumb', il tuo 'oldList' avrebbe conforme a numbersB nel codice di esempio sopra ...


anche il comment da 'Stonetip' (del quale grazie) ...

More succinct: if(numbersA.Except(numbersB).Any()) { // do something } 
+0

Penso che quelle parole siano poco confuse e "oldList is the è solo la vecchia lista (le impostazioni correnti prima che l'utente le cambi)" significa che potrebbe dire che una è già salvata nelle impostazioni e la lista corrente significa non salvare. Potrebbe non avere due collezioni, ma una già salvata (che ci virtualizza come una collezione) e una nella lista. Se ha entrambe le collezioni in memoria, allora è buono da usare tranne il metodo LINQ. +1 per l'utilizzo di LINQ (approccio conciso). Gli parliamo di maggiori descrizioni sul suo lavoro. – King

+0

@Dumb, ciao e buon anno! Potresti usare la funzione 'modifica' per modificare la parte confusa in modo che sia chiara? Intendi dire che le impostazioni non intendono essere persistenti? –

+0

Buon anno! Sto aspettando che chiarisca un po 'di più in modo che capiremo esattamente di cosa ha bisogno e possiamo modificarli. Sì. Ho l'idea che i suoi dati non siano persistenti. Ma certamente due versioni non sembrano coerenti con ciò che ha detto nei commenti! Quindi Mebbe vuole controllare ogni volta che qualcosa viene fatto con listview, motivo per cui ho suggerito di verificare gli eventi per l'approccio listview. Ma se ha due versioni di dati persistenti, ti consiglierei di usare il tuo approccio! – King

0

I th inchiostro, ti stai concentrando sull'approccio sbagliato. Non si dovrebbe confrontare il contenuto di 2 elenchi associati a ListView, anche perché la quantità di articoli che contengono può essere eccessivamente grande.

  • E 'meglio concentrarsi sulla definizione di un singolo (se questo è possibile) e maniera uniforme per essere in grado di modificare il contenuto di una raccolta dalle API, fornendo alla classe dei consumatori un modo generale di essere in grado di cambia qualcosa nella collezione. Se si utilizza tale metodo, è possibile tenere un valore booleano flag che identifica se qualcosa è stato modificato.

  • Oppure si può supporre che, se qualcuno utilizza il metodo set all'interno della proprietà della raccolta associata, significa che la raccolta è stata modificata.

In altre parole, relè o sul flusso di lavoro predefinito dell'applicazione, oppure definire un API per cambiare i contenuti, in modo da essere in grado di capire quando e se il contenuto delle collezioni è stato cambiato .

E un'altra nozione ancora: non ha senso lasciare all'utente fare clic su Save e non salvare. Se è possibile fare clic su Save, il comando richiesto dall'utente deve essere eseguito. Se si è cauti sulle prestazioni (non si desidera salvare qualcosa, se non è stato modificato dall'ultimo salvataggio), disabilitare il pulsante Save, se il salvataggio non è appropriato. In altre parole, crea un numero UI e si comporta come previsto dalla tua app. Rendere all'utente chiaro cosa app fa ora e cosa no.

Problemi correlati