2011-10-10 7 views
13

Recentemente ho riscontrato un problema in cui ho un ObservableCollection associato a un ListView. Le persone sono una struttura che ho scritto. Finché imposto il/i valore/i degli oggetti People prima del binding, tutto sembra funzionare correttamente. Tuttavia, quando provo ad impostare i valori dalla GUI in fase di runtime, gli oggetti sottostanti non sembrano riflettere la modifica.Perché il binding a una stringa non funziona?

Alla fine ho risolto questo problema semplicemente cambiando le persone da una struttura a una classe. Non sono stati necessari altri cambiamenti.

Qualcuno può spiegarmi perché questo è?

+5

fai a sapere la differenza tra struct e la classe? –

risposta

21

L'associazione ottiene una copia di struct poiché le strutture vengono passate per valore ai metodi. Se l'associazione aggiorna qualcosa; una copia in memoria da qualche parte viene modificata e quindi l'oggetto originale non viene aggiornato.

2

Poiché la struttura viene passata per valore al controllo, pertanto quando si apportano modifiche nell'interfaccia utente, WPF riporta le modifiche su un'altra istanza di People.

Cambiarlo in una classe e funzionerà.

A meno che non si comprenda perfettamente lo scopo di struct, suggerisco di non utilizzarlo.

2

Il ListView è un ItemsControl e funziona sia in modalità diretta, dove si popolano è Articoli dichiarando oggetti ListViewItem severl in XAML o in modalità ItemsSource in cui è stata impostata una rilegatura sulla proprietà ItemsSource

See this Dr. WPF article for a good explanation.

In entrambi i casi, ListView.Items è un ItemCollection che è un oggetto CollectionView, vale a dire che gli elementi non sono la raccolta effettiva fornita alla proprietà ItemsSource ma una copia normalizzata della raccolta fornita che consente al framework, ad esempio, di accedere a IEnumerable sottostante per indice anche se IEnumerable non fornisce un indicizzatore.

Poiché ListView utilizza una copia, quando utilizza una raccolta di istanze di Class può creare copie dei riferimenti, entrambi i riferimenti puntano allo stesso oggetto in memoria in modo che gli effetti della modifica dei valori in uno dei riferimenti siano visibili attraverso l'altro riferimento, ma quando usa una raccolta di strutture che sono tipi di valore, deve fare copie dei valori, piuttosto che avere due riferimenti che puntano allo stesso oggetto, allora si hanno due oggetti di valore distinti.

1

Per tutti gli interessati a questo argomento: L'ho ottenuto in esecuzione, con un Combobox e Objectdataprovider. "ItemsSource" è la struct, ma "SelectedItem" è scritto da qualche altra parte. Eccolo:

<!--resources--> 
    <ObjectDataProvider x:Key="StructValues" 
         MethodName="GetValues" 
         ObjectType="{x:Type local:MyStruct}"> 
     <ObjectDataProvider.MethodParameters> 
      <x:Type TypeName="local:MyStruct" /> 
     </ObjectDataProvider.MethodParameters> 
    </ObjectDataProvider> 

    <ComboBox Margin="0,5" 
         VerticalAlignment="Center" 
         ItemsSource="{Binding Source={StaticResource StructValues}}"/> 

e questo è come lo struct assomiglia:

public struct MyStruct 
{ 
    public const string A = "A"; 
    public const string B = "B"; 
    public const string C = "C"; 

    public static IEnumerable GetValues(Type type) 
    { 
     List<String> retVals = new List<string>(); 
     FieldInfo[] fi = type.GetFields(); 
     foreach (FieldInfo info in fi) 
     { 
      retVals.Add(info.Name); 
     } 
     return retVals; 
    } 
} 
Problemi correlati